Vue 2.x computed 属性 在其依赖项与内联数据绑定时不会更新

Vue 2.x computed property is not updated when its dependencies are binded with inline data

我在尝试从 Vue 1.0.27 迁移到 Vue 2.0.1 时遇到以下问题。

EDIT 添加了工作 JSFidle

情况:

我构建了一个非常简单的应用程序,它获取任务列表(来自模型)并将它们显示在无序列表中,以及未标记为已完成的任务数(即剩余任务) ). ViewModel 和 Model 的代码如下所示:

 /*************
 *  ViewModel *
 * ***********/

var vm = new Vue({
    el: '#my-app',
    data: data
});


 /*************
 *    Model   *
 * ***********/

var data = {
    my_tasks: [
        {body: "Go to the doctor", completed: false},
        {body: "Go to the bank", completed: false},
        {body: "Go to the zoo", completed: false}
    ],
};

为了显示任务列表,我使用了 <task-list> 自定义组件。组件:

自定义组件的代码如下所示

 /*****************
 *    Component   *
 * ***************/

Vue.component('task-list', {
    template: '#task-list-template',
    props: ['tasks'],
    computed: {
        remaining: function () {
            return this.tasks.filter(
                this.inProgress
            ).length;
        }
    },
    methods: {
        /**
         * Toggle the completed status of a task
         * @param item
         */
        toggleCompletedStatus: function (item) {
            return item.completed = !item.completed;
        },
        /**
         * Returns true when task is in progress (not completed)
         * @param item
         */
        inProgress: function (item) {
            return !item.completed;
        }

    },
});

<template id="task-list-template">
    <div>
        <h3>My tasks list ( {{ remaining }} )</h3>
        <ul>
            <li v-for="task in tasks" @click="toggleCompletedStatus(task)">
                {{ task.body }}
            </li>
        </ul>
    </div>
</template>

最后在我的 视图 中,我使用 v-bind 指令 将组件的任务 属性 与数据绑定.

 /************
 *    View   * <-- works fine with both Vue 1.X and 2.x
 * **********/

div id="my-app">
    <task-list :tasks="my_tasks"></task-list>
</div>

问题:

如果我尝试以内联方式传递任务列表,则计算的 属性 remaining 在用户单击任务时不会更新。(即当 task.completed 属性 改变时)

 /************
 *    View   * <-- works in Vue 1.x, NOT working with Vue 2.x
 * **********/

div id="my-app">
    <task-list :tasks="[{body: "Go to the doctor", completed: false}, {body: "Go to the bank", completed: false}, {body: "Go to the dentist", completed: false}]"></task-list>
</div>

如果我尝试从服务器传递数据,也会出现同样的问题。下面的示例在后端使用 Laravel 5.3:

 /************
 *    View   * <-- works in Vue 1.x, NOT working with Vue 2.x
 * **********/

div id="my-app">
    <task-list :tasks="{{$tasks}}"></task-list> <!-- {{$tasks}} are the json encoded data from the server -->
</div>

感谢任何帮助

这是正常行为,我会让你查看有关道具的迁移指南:http://vuejs.org/guide/migration.html#Prop-Mutation-deprecated4

此处您的示例更新为适用于 Vue 2.0:

 /*****************
 *    Component   *
 * ***************/

Vue.component('task-list', {
    template: '#task-list-template',
    props: ['tasks-data'],
    data: function () {
     return { tasks: [] };
    },
    computed: {
        remaining: function () {
            return this.tasks.filter(
                this.inProgress
            ).length;
        }
    },
    created: function () {
     this.tasks = this.tasksData; // Set default properties
    },
    methods: {
        /**
         * Toggle the completed status of a task
         * @param item
         */
        toggleCompletedStatus: function (item) {
            return item.completed = !item.completed;
        },
        /**
         * Returns true when task is in progress (not completed)
         * @param item
         */
        inProgress: function (item) {
            return !item.completed;
        }
    }
});


 /*************
 *  ViewModel *
 * ***********/

new Vue({
    el: '#my-app'
});
<script src="https://unpkg.com/vue@2.0.1/dist/vue.js"></script>
<div id="my-app">
  <task-list :tasks-data="[{body: 'Hello all', completed: false},{body: 'Goodbye all', completed: false}]"></task-list> 
</div>

<!-- Template for custom component -->
<template id="task-list-template">
    <div>
        <h3>Remaining task {{ remaining }}</h3>
        <ul>
            <li v-for="task in tasks" @click="toggleCompletedStatus(task)">
                {{ task.body }}
            </li>
        </ul>
    </div>
</template>
  

如您所见,我在创建的钩子中设置了数据中的任务,以便 Vue 可以监听更改并更新模板。