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

时间:2017-11-28 23:33:45

标签: design-patterns vue.js components edit cancellation

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

我的设置如下: 一个ul列表,其中包含我要呈现或编辑的大部分数据。 在“li”的一部分上,有一个子组件可以显示数据的一部分,它是连接到该对象的资源列表,也可以处理新资源的推送。

我还希望用户使用按钮启用行的启用编辑模式,然后按钮进行更新和取消。

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

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

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

我可以在这里使用另一种模式吗?

1 个答案:

答案 0 :(得分:1)

我认为您提到的“可变行”问题是通过传递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
-->