【问题标题】:Vue.js passing item in items to component as prop: will I be modifying prop?Vue.js 将项目中的项目作为道具传递给组件:我会修改道具吗?
【发布时间】:2018-02-17 23:07:49
【问题描述】:

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

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

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

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

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

如果我理解正确,我不应该尝试按照我的方式更改 todo 文本,因为即使它很难工作,我正在更改子组件中的一个 prop(因为每个 todo 都通过一个道具)。

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

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

【问题讨论】:

标签: vue.js


【解决方案1】:

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

“有效”与“最佳实践”不同。最佳实践是只有数据项的所有者才能修改它。这需要一定数量的额外编码来发出和处理事件。您可能会认为不值得付出额外的努力,而且大多数时候这不会对您不利,尤其是在简单的应用程序中。在复杂的应用程序中,您可能会发现使用完全封装的组件进行单元测试效果更好。

下面的 sn-p 是在没有 custom 事件的情况下处理它的一种方法:捕获 native change 事件(您可以捕获本机 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;
    }
  }
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<div id="app-7">
  <todo-item v-for="item in groceryList" :todo="item" :key="item.id" @change.native="setText(item, $event.target.value)">
  </todo-item>
  <div v-for="item in groceryList">
    {{item.text}}
  </div>
</div>

【讨论】:

    猜你喜欢
    • 2021-08-15
    • 2018-08-01
    • 2018-03-11
    • 1970-01-01
    • 2018-05-31
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    相关资源
    最近更新 更多