Vue.js - 使用子组件更新或撤消模式

Vue.js - Updated or undo pattern with child component

我在从子组件更新正确的对象时遇到问题。

我的设置如下: 一个 ul 列表,其中包含我要呈现或编辑的大部分数据。 在"li"的一部分上,有一个子组件来展示那部分数据,也就是那个对象连接的资源列表,同时也处理新资源的推送。

我还希望用户有一个用于启用行编辑模式的按钮,然后是用于更新和取消的按钮。

我面临的问题是找出我应该编辑然后保存的对象。我现在正在做的是尝试将行中的数据复制到一个 mutableRow 中,然后我将其用作输入控件的模型,而当用户未处于编辑模式时显示实际的行数据。在更新方法中,我 post 到数据库并更新了行对象。

ul
  li(v-for="row in rows")
    p(v-if="!row.editing") {{ row.name }}
    input(v-else, v-model="mutableRow.name")
    resources(:row="row")
    button(v-if="!row.editing") Start edit
    template(v-else)
      button Update
      button Cancel

这是正确的做法吗?如果是这样,我应该如何处理发送到我的子组件的道具?我尝试通过 this.$parent.mutableRow 获取 mutableRow,我尝试使用 v-if 切换 "resource(:row="row")" 并在编辑模式下发送 mutableRow,但随后我结束了以某种方式更改组件中的两个对象。

我可以在这里使用其他模式吗?

我认为您提到的 "mutable row" 问题可以通过传递 rows[index] 而不是 row 来解决。无论如何,这就是 .sync 工作所需要的。

我下面的例子实现了我在评论中的建议:一个单独的组件,它有自己的数据副本和自己的编辑模式控件。当您开始编辑时,道具数据被复制到本地数据。单击“更新”时,会发出一个事件,父级(通过 sync)将编辑的数据复制到行中。如果单击取消,则不会发出任何事件,编辑结束。

new Vue({
  el: '#app',
  data: {
    rows: [{
      name: "Test",
      thingy: 4,
      resources: [{
        title: "Title",
        price: 5000
      }]
    }]
  },
  components: {
    rowEditor: {
      template: '#row-editor-t',
      props: ['row'],
      data() {
        return {
          editing: false,
          localRow: null
        };
      },
      methods: {
        startEditing() {
          this.editing = true;
          this.localRow = JSON.parse(JSON.stringify(this.row));
        },
        stopEditing() {
          this.editing = false;
        },
        update() {
          this.$emit('update:row', this.localRow);
          this.stopEditing();
        },
        cancel() {
          this.stopEditing();
        }
      }
    }
  }
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app">
  <ul>
    <li v-for="row, index in rows" is="row-editor" :row.sync="rows[index]">
    </li>
  </ul>
</div>

<template id="row-editor-t">
  <li>
    <div v-if="editing">
      <input v-model="localRow.name">
      <div v-for="resource in localRow.resources">
        <input v-model="resource.title"><input v-model="resource.price">
      </div>
    </div>
    <div v-else>
      {{row.name}}
      <div v-for="resource in row.resources">
        {{resource.title}}: {{resource.price}}
      </div>
    </div>
    <div v-if="editing">
      <button type="button" @click="update">Update</button>
      <button type="button" @click="cancel">Cancel</button>
    </div>
    <button v-else @click="startEditing">Start edit</button>
  </li>
</template>

<!--
ul
  li(v-for=" row in rows ")
    p(v-if="!row.editing ") {{ row.name }}
    input(v-else, v-model="mutableRow.name ")
    resources(:row="row ")
    button(v-if="!row.editing ") Start edit
    template(v-else)
      button Update
      button Cancel
-->