如何延迟将 Ajax 数据传递给 child 组件?
How to defer passing of Ajax data to child components?
我正在使用 Vue 2.0 使用 built-in parent-child 通信构建一个简单的 to-do 应用程序。直接附加到Vue实例(new Vue({...}
)的parent元素如下:
<!-- 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
属性:[=27= 将数据从 <tasks>
传递到 3 个 <task-lists>
中的每一个]
<task-list :tasks="tasks"></task-list>
<task-list :tasks="incompleteTasks"></task-list>
<task-list :tasks="completeTasks"></task-list>
注意,我没有使用共享(全局)状态,因为每个列表都需要 不同的 部分数据,即使这些部分数据属于同一个存储。但问题是 :tasks
在 调用 Ajax 之前被分配了一个空数组 ;正如我猜测的那样,道具是不可变的,因此当在 parent <tasks>
中获取数据时,child <task-list>
中的 tasks
永远不会更新。事实上,<task-list>
是先创建的(见日志),然后 只有 使用 Ajax.
获取数据
问题
- 我如何推迟数据从
<tasks>
到我的 <task-list>
的传递?我如何确保所有组件都引用动态更新的单一事实来源?
- 有没有办法解决这个 parent-child 与 "vanilla" Vue.js 的通信问题?或者我需要使用 Vuex 或类似的东西吗?
- 我使用属性将数据传递给 children 是否正确?或者我应该在全局变量中使用共享存储?
问题在这里:mounted() { this.taskList = this.tasks; ...}
在 TaskList.vue
内,因为 taskList
属性 仅在 mounted
事件上更新。
Vue 中有一个简单的解决方案:您应该使 taskList
成为一个 computed property
,这取决于 props,这样当 parent 数据更改时,您计算的 属性 就会更新:
props: ['tasks'],
computed: {
taskList: function() {
return this.tasks;
}
}
不要忘记从 data
块中删除 taskList
。
此外,我会将 v-model="task.complete"
重写为 @change="$emit('something', task.id)"
以通知 parent 组件状态已更改(并收听)。否则 parent 永远不会知道该框已被选中。然后,您可以在 parent 组件上侦听此事件以相应地更改任务状态。更多阅读:https://vuejs.org/v2/guide/components.html#Custom-Events
也可以使用vue实例watch属性
watch:{
tasks(newVal){
this.taskList = newVal;
//do something
}
}
我正在使用 Vue 2.0 使用 built-in parent-child 通信构建一个简单的 to-do 应用程序。直接附加到Vue实例(new Vue({...}
)的parent元素如下:
<!-- 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
属性:[=27= 将数据从 <tasks>
传递到 3 个 <task-lists>
中的每一个]
<task-list :tasks="tasks"></task-list>
<task-list :tasks="incompleteTasks"></task-list>
<task-list :tasks="completeTasks"></task-list>
注意,我没有使用共享(全局)状态,因为每个列表都需要 不同的 部分数据,即使这些部分数据属于同一个存储。但问题是 :tasks
在 调用 Ajax 之前被分配了一个空数组 ;正如我猜测的那样,道具是不可变的,因此当在 parent <tasks>
中获取数据时,child <task-list>
中的 tasks
永远不会更新。事实上,<task-list>
是先创建的(见日志),然后 只有 使用 Ajax.
问题
- 我如何推迟数据从
<tasks>
到我的<task-list>
的传递?我如何确保所有组件都引用动态更新的单一事实来源? - 有没有办法解决这个 parent-child 与 "vanilla" Vue.js 的通信问题?或者我需要使用 Vuex 或类似的东西吗?
- 我使用属性将数据传递给 children 是否正确?或者我应该在全局变量中使用共享存储?
问题在这里:mounted() { this.taskList = this.tasks; ...}
在 TaskList.vue
内,因为 taskList
属性 仅在 mounted
事件上更新。
Vue 中有一个简单的解决方案:您应该使 taskList
成为一个 computed property
,这取决于 props,这样当 parent 数据更改时,您计算的 属性 就会更新:
props: ['tasks'],
computed: {
taskList: function() {
return this.tasks;
}
}
不要忘记从 data
块中删除 taskList
。
此外,我会将 v-model="task.complete"
重写为 @change="$emit('something', task.id)"
以通知 parent 组件状态已更改(并收听)。否则 parent 永远不会知道该框已被选中。然后,您可以在 parent 组件上侦听此事件以相应地更改任务状态。更多阅读:https://vuejs.org/v2/guide/components.html#Custom-Events
也可以使用vue实例watch属性
watch:{
tasks(newVal){
this.taskList = newVal;
//do something
}
}