我正在使用内置的父子通信使用Vue 2.0构建一个简单的待办事项应用程序 . 直接附加到Vue实例( new Vue({...}
)的父元素如下:
<!-- Tasks.vue -->
<template>
<div>
<create-task-form></create-task-form>
<task-list :tasks="tasks"></task-list>
<task-list :tasks="incompleteTasks"></task-list>
<task-list :tasks="completeTasks"></task-list>
</template>
<script>
import CreateTaskForm from './CreateTaskForm.vue';
import TaskList from './TaskList.vue';
export default {
components: { CreateTaskForm, TaskList },
data() { return { tasks: [] }; },
created() { // Ajax call happens here...
axios.get('/api/v1/tasks')
.then(response => {
this.tasks = response.data;
console.log(this.tasks); // THIS IS LOGGED LAST
});
},
computed: {
completeTasks() {
return this.tasks.filter(task => task.complete);
},
incompleteTasks() {
return this.tasks.filter(task => task.complete);
}
}
}
</script>
我们的想法是 <tasks></tasks>
将显示一个表单来创建一个新任务,以及3个列表 - 所有任务,不完整和完整的任务 . 每个列表都是相同的组件:
<!-- TaskList.vue -->
<template>
<ul>
<li v-for="task in taskList">
<input type="checkbox" v-model="task.complete"> {{ task.name }}
</li>
</ul>
</template>
<script>
export default {
data() { return { taskList: [] }; },
props: ['tasks'],
mounted() {
this.taskList = this.tasks;
console.log(this.tasks); // THIS IS LOGGED FIRST
}
}
</script>
问题
如您所见,我正在尝试使用动态 :tasks
属性将数据从 <tasks>
传递到3 <task-lists>
中的每一个:
<task-list :tasks="tasks"></task-list>
<task-list :tasks="incompleteTasks"></task-list>
<task-list :tasks="completeTasks"></task-list>
注意,我没有使用共享(全局)状态,因为每个列表都需要 different 部分数据,即使这些数据部分属于同一个存储 . 但问题是 :tasks
被分配了一个空数组 before Ajax调用发生了;并且正如我猜测的那样,道具是不可变的,因此当在父 <tasks>
中获取数据时,子 <task-list>
中的 tasks
永远不会更新 . 实际上,首先创建 <task-list>
(参见日志),然后使用Ajax获取数据 only then .
问题
-
如何将数据从
<tasks>
传递到<task-list>
?如何确保所有组件都引用动态更新的单一事实来源? -
有没有办法用"vanilla" Vue.js解决这个父子沟通问题?或者我需要使用Vuex或类似的东西吗?
-
我是否正确使用属性将数据传递给孩子?或者我应该在全局变量中使用共享存储?
2 回答
问题在于:
mounted() { this.taskList = this.tasks; ...}
在TaskList.vue
内,因为taskList
属性仅在mounted
事件上更新 .在Vue中有一个简单的解决方案:你应该使
taskList
一个computed property
依赖于道具,这样当父数据改变时你的计算属性会更新:不要忘记从
data
块中删除taskList
.此外,我会将
v-model="task.complete"
重写为@change="$emit('something', task.id)"
,以通知父组件状态已更改(并收听) . 否则父母将永远不会知道该框已被选中 . 然后,您可以在父组件上侦听此事件,以相应地更改任务状态 . 更多阅读:https://vuejs.org/v2/guide/components.html#Custom-Events您还可以使用vue实例的 watch 属性