Vue.js将项目中的项目作为prop传递给组件:我将修改prop吗?

时间:2017-09-09 01:31:20

标签: vue.js

Vue.js的新手。从文档中,一个简单的例子是使用组件来呈现列表中的每个项目,如下所示:

<todo-item
      v-for="item in groceryList"
      v-bind:todo="item"
      v-bind:key="item.id">
    </todo-item>

Vue.component('todo-item', {
  // The todo-item component now accepts a
  // "prop", which is like a custom attribute.
  // This prop is called todo.
  props: ['todo'],
  template: '<li>{{ todo.text }}</li>'
})

var app7 = new Vue({
  el: '#app-7',
  data: {
    groceryList: [
      { id: 0, text: 'Vegetables' },
      { id: 1, text: 'Cheese' },
      { id: 2, text: 'Whatever else humans are supposed to eat' }
    ]
  }
})

(资料来源:https://vuejs.org/v2/guide/index.html#Composing-with-Components

我的问题是:更改的正确方法是什么,例如待办事项文字?请注意:我做想要更改父数据,可能的重复是人们不想更改父数据的情况。

我最初的想法是在组件模板中使用<input v-model="todo.text">。它有效。我发现这很好,因为它更新了根组件data属性中的待办事项数组,这意味着我不必编写事件来使更改的数据冒泡。

但是有一个问题。阅读组件中的文档,我看到了:

所有道具在子属性和父属性之间形成单向向下绑定:当父属性更新时,它将向下流向孩子,但不是相反这可以防止子组件意外改变父级状态,这可能会使您的应用程序的数据流更难以推理。 此外,每次更新父组件时,子组件中的所有道具都将使用最新值进行刷新。 这意味着您不应该尝试改变子组件内的prop。如果你这样做,Vue会在控制台中警告你。

如果我理解正确,我不应该尝试按照我的方式更改待办事项文本,因为即使它很难操作,我也会更改子组件内的道具(因为每个待办事项都通过子组件传递给子组件一个道具)。

但文档清楚地说Vue会警告我不要在控制台中使用这种做法,但我没有看到任何警告。

此外,如果这不是最佳做法,我应该如何正确更改待办事项名称?

1 个答案:

答案 0 :(得分:2)

如果您修改道具的成员,Vue将不会注意到。如果你试图修改道具本身,它只会注意到(并警告)。

“它有效”与“最佳实践”不同。最佳做法是仅对数据项的所有者进行修改。这需要一定量的额外编码来发射和处理事件。您可能认为不值得付出额外的努力,并且大部分时间都不会让您感到痛苦,特别是在简单的应用程序中。在复杂的应用程序中,您可能会发现使用完全封装的组件可以更好地进行单元测试。

下面的代码段是在没有自定义事件的情况下处理它的一种方法:捕获原生 change事件(您可以捕获本机{{1}如果您愿意,可以选择事件。)

input
Vue.component('todo-item', {
  // The todo-item component now accepts a
  // "prop", which is like a custom attribute.
  // This prop is called todo.
  props: ['todo'],
  template: '<input :value="todo.text">'
})

var app7 = new Vue({
  el: '#app-7',
  data: {
    groceryList: [{
        id: 0,
        text: 'Vegetables'
      },
      {
        id: 1,
        text: 'Cheese'
      },
      {
        id: 2,
        text: 'Whatever else humans are supposed to eat'
      }
    ]
  },
  methods: {
    setText(item, event) {
      item.text = event;
    }
  }
})