javascript - Vue root 和任何子组件之间的通信

标签 javascript vue.js vuejs2

我有一系列深入多个级别的组件。每个组件都有自己的数据片段,通过 AJAX 加载这些数据并用于呈现子组件的每个实例。 days 父模板例如:

<template>
    <accordion :one-at-atime="true" type="info">
        <panel :is-open="index === 0" type="primary" :header="'Day ' + day.day" v-for="(day, index) in days" :key="day.id">
            <br/>
            <div class="panel panel-success">
                <div class="panel-heading">
                    <h3 class="panel-title">Cycles</h3>
                </div>
                <div class="panel-body">
                        <cycles
                            :day="day"
                        >
                        </cycles>
                </div>
            </div>
        </panel>
    </accordion>
</template>

cycles 子模板例如:

<template>
    <accordion :one-at-atime="true" type="info">
        <panel :is-open="index === 0" type="primary" :header="'Week ' + cycle.week + ': ' + cycle.name" v-for="(cycle, index) in cycles" :key="cycle.id">
            <form v-on:submit.prevent="update">
                ....misc input fields here...
<button type="button" class="btn btn-warning" v-if="cycle.id" v-on:click="destroy">Delete</button>
            </form>
        </panel>
    </accordion>
</template>

<script>
    export default {
        props: [
            'day'
        ],
        data() {
            return {
                cycles: []
            }
        },
        beforeMount: function () {
            var self = this;

            if (this.cycles.length === 0) {
                axios.get('/plans/days/' + this.day.id + '/cycles')
                    .then(function (response) {
                        self.cycles = response.data;
                    })
                    .catch(function (error) {
                        console.log(error);
                    });
            }
        },
        methods: {
            destroy: function (event) {
                var self = this;

                axios.delete('/plans/cycles/' + event.target.elements.id.value)
                    .then(function (response) {
                        self.cycles.filter(function (model) {
                            return model.id !== response.data.model.id;
                        });
                    })
                    .catch(function (error) {
                        console.log(error);
                    });
            }
        }
    }
</script>

每个cycles组件然后在v-for循环中渲染另一个组件,该循环渲染另一种类型的组件,依此类推。创建的是一个树状的组件结构。

当我需要向服务器发送通用请求,然后更新调用它的组件中的数据时,我不想在每个组件中重复该请求方法。我宁愿在根 Vue 实例上只拥有该方法的一个实例。

例如,这将是首选:

const app = new Vue({
    el: '#app',
    store,
    created: function () {
        this.$on('destroy', function (event, type, model, model_id, parent_id) {
            this.destroy(event, type, model, model_id, parent_id);
        })
    },
    methods: {
        destroy: function (event, type, model, model_id, parent_id) {
            var self = this;

            axios.delete('/plans/' + type + '/' + model_id)
                .then(function (response) {
                    model = model.filter(function (model) {
                        return model.id !== response.data.model.id;
                    });

                    this.$emit('modified-' + type + '-' + parent_id, model);
                })
                .catch(function (error) {
                    console.log(error);
                });
        }
    }
});

然后在cycles.vue删除按钮中单击时调用:

<button type="button" class="btn btn-warning" v-if="cycle.id" v-on:click="$root.$emit('destroy', event, 'cycles', cycles, cycle.id, day.id)">Delete</button>

并将其添加到 cycles.vue 事件中:

    created: function () {
        this.$on('modified-cycles-' + this.day.id, function (cycles) {
            this.cycles = cycles;
        })
    },

但是,这不起作用,因为子元素永远不会从根元素获取发出的 'modified-' + type + '-' + Parent_id 事件。

我还尝试了 this.$children.$emit('modified-' + type + '-' + Parent_id, model); 但这也不起作用。

Vue 2.5.16 的方法是什么?有没有比我目前使用的更好的设计模式?

最佳答案

每个 Vue 实例(根实例和子实例)都是一个独立的事件中心。

您在实例上 $emit 事件,并且可以在同一实例上使用 $on 订阅事件通知。

您可以使用 this.$root.$on()this.$root.$emit() 将根实例用作事件总线并实现你的目的。

但是,我不太清楚您想要实现什么关注点分离,因此我不准备提供更好的建议。

关于javascript - Vue root 和任何子组件之间的通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49520891/

相关文章:

javascript - Socket.io 对接会

css - 动态覆盖 Vuetify 类

css - 验证视差流体模板问题

javascript - 如何在没有 Node Js bundler 的情况下通过 CDN 在 Django 中使用 Vue 3?

javascript - 单击按钮即可下载图像数组

javascript - Three.js 在 OrbitControls 中限制平移

javascript - 即使可用堆内存远大于已用内存,也会出现堆内存不足的错误

javascript - Ajax 中的 URL open()

vuejs2 - Vue2 : is possible to pass multiple props to component?

javascript - 使用 Vue 获取 img currentSrc