Vue 2 - 变异道具 vue-warn

新手上路,请多包涵

我开始 https://laracasts.com/series/learning-vue-step-by-step 系列。我在 Vue、Laravel 和 AJAX 课程上停了下来,但出现了这个错误:

vue.js:2574 [Vue 警告]:避免直接改变 prop,因为只要父组件重新渲染,该值就会被覆盖。相反,使用基于道具值的数据或计算属性。正在变异的道具:“列表”(在组件中找到)

我在 main.js 中有这段代码

Vue.component('task', {
    template: '#task-template',
    props: ['list'],
    created() {
        this.list = JSON.parse(this.list);
    }
});
new Vue({
    el: '.container'
})

当我覆盖列表道具时,我知道问题出在 created() 中,但我是 Vue 的新手,所以我完全不知道如何解决它。有谁知道如何(并请解释原因)修复它?

原文由 Dariusz Chowański 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 495
2 个回答

这与 在 Vue 2 中对 prop 进行本地变异被视为反模式 这一事实有关

如果你想在 本地改变一个 prop ,你现在应该做的是在你的 data 中声明一个使用 props 值作为初始值的字段,然后改变副本:

 Vue.component('task', {
 template: '#task-template',
 props: ['list'],
 data: function () {
 return {
 mutableList: JSON.parse(this.list);
 }
 }
 });

您可以在 Vue.js 官方指南 上阅读更多相关信息


注意 1: 请注意, _您的 propdata 不应 使用相同的名称_,即:

 data: function () { return { list: JSON.parse(this.list) } } // WRONG!!

注意 2: 由于我觉得关于 propsreact 有一些混淆,我建议你看看 这个 线程

原文由 ira 发布,翻译遵循 CC BY-SA 4.0 许可协议

Vue 模式是 props 向下和 events 向上。这听起来很简单,但是在编写自定义组件时很容易忘记。

从 Vue 2.2.0 开始,您可以使用 v-model (具有 计算属性)。我发现这种组合在组件之间创建了一个简单、干净且一致的接口:

  • 传递给您的组件的任何 props 仍然是反应性的(即,它没有被克隆,也不需要 watch 函数来在检测到更改时更新本地副本)。
  • 更改会自动发送给父级。
  • 可以与多个级别的组件一起使用。

计算属性允许单独定义 setter 和 getter。这允许 Task 组件重写如下:

 Vue.component('Task', {
    template: '#task-template',
    props: ['list'],
    model: {
        prop: 'list',
        event: 'listchange'
    },
    computed: {
        listLocal: {
            get: function() {
                return this.list
            },
            set: function(value) {
                this.$emit('listchange', value)
            }
        }
    }
})

模型 属性定义了哪个 propv-model 关联,以及哪个事件将在更改时发出。然后您可以从父级调用此组件,如下所示:

 <Task v-model="parentList"></Task>

listLocal 计算属性在组件中提供了一个简单的 getter 和 setter 接口(将其视为私有变量)。 Within #task-template you can render listLocal and it will remain reactive (ie, if parentList changes it will update the Task component).您还可以通过调用设置器(例如 this.listLocal = newList listLocal 来改变 --- ,它会将更改发送给父级。

这种模式的优点在于,您可以将 --- 传递给 listLocal 的子组件(使用 Task v-model ),并将更改传播到子组件–顶级组件。

例如,假设我们有一个单独的 EditTask 组件用于对任务数据进行某种类型的修改。通过使用相同的 v-model 和计算属性模式,我们可以将 listLocal 传递给组件(使用 v-model ):

 <script type="text/x-template" id="task-template">
    <div>
        <EditTask v-model="listLocal"></EditTask>
    </div>
</script>

如果 EditTask 发出更改,它将适当地调用 set()listLocal 上,从而将事件传播到顶层。同样, EditTask 组件也可以使用 v-model 调用其他子组件(例如表单元素)。

原文由 chris 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题