如何将Ajax数据传递给子组件?

时间:2017-05-25 11:46:58

标签: vue.js vuejs2 vue-component

我正在使用内置的父子通信构建一个使用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>属性将数据从<task-lists>传递到3 :tasks中的每一个:

<task-list :tasks="tasks"></task-list>

<task-list :tasks="incompleteTasks"></task-list>

<task-list :tasks="completeTasks"></task-list>

注意,我没有使用共享(全局)状态,因为每个列表都需要不同的部分数据,即使这些数据部分属于同一个商店。但问题是,在发生Ajax调用之前,:tasks被分配了一个空数组 ;而且正如我猜测的那样,道具是不可变的,因此当在父tasks中提取数据时,子<task-list>中的<tasks>永远不会更新。实际上,首先创建<task-list>(参见日志),然后 使用Ajax获取数据。

问题

  • 如何推迟从<tasks><task-list>的数据传递?如何确保所有组件都引用了动态更新的单一事实来源?
  • 有没有办法用&#34; vanilla&#34;解决这个亲子沟通问题? Vue.js?或者我需要使用Vuex或类似的东西吗?
  • 我是否正确使用属性将数据传递给孩子?或者我应该在全局变量中使用共享存储吗?

2 个答案:

答案 0 :(得分:4)

问题在于:mounted() { this.taskList = this.tasks; ...}TaskList.vuetaskList属性仅在mounted事件中更新。

在Vue中有一个简单的解决方案:你应该使taskList成为computed property,这取决于道具,这样当父数据发生变化时,你的计算属性就会更新:

props: ['tasks'],
computed: {
  taskList: function() {
    return this.tasks;
  }
}

不要忘记从taskList阻止中移除data

此外,我会将v-model="task.complete"重写为@change="$emit('something', task.id)",以通知父组件状态已更改(并收听)。否则父母将永远不会知道该框已被选中。然后,您可以在父组件上侦听此事件,以相应地更改任务状态。更多阅读:https://vuejs.org/v2/guide/components.html#Custom-Events

答案 1 :(得分:1)

您还可以使用vue实例的 watch 属性

ParseInteger32