首页 文章

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

提问于
浏览
0

我正在使用内置的父子通信使用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 回答

  • 1

    问题在于: mounted() { this.taskList = this.tasks; ...}TaskList.vue 内,因为 taskList 属性仅在 mounted 事件上更新 .

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

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

    不要忘记从 data 块中删除 taskList .

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

  • 4

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

    watch:{
       tasks(newVal){
            this.taskList = newVal;
          //do something
       }
    }
    

相关问题