兄弟组件的通讯问题?迷之解决方案

有一个需求,就是一个组件把uuid传给他的兄弟组件.在网上查阅的资料,用的也是大家推荐的eventBus,创建一个空的Vue实例对象,作为媒介进行传值.区别之处在于:

网上教程是用按钮触发这个传值的过程的 ,就是两个组件都已经加载完毕的前提下

而我的需求是:当两个组件加载的时候就把uuid传给对方
引入一个空的vue对象 eventBus

a,b两个组件,a组件mounted的时候 eventBus.$emit("事件名",uuid)

b组件created的时候this.$on 进行绑定

然后经过多次试验,得出的结论是:

a组件进行$emit的时候b组件还没有绑定实践,所以虽然uuid生成了,但是没有传过去,这个时候我灵机一动:把a组件中mounted的代码改成了这样子:

mounted() {
setTimeout(()=>{this.$emit('事件名',uuid)},0)
}

然后就莫名其妙的成功

b组件也接收到了uuid

虽然成功了 但是才疏学浅 还没有搞懂原理,求大家不吝赐教,在下:来世结草衔环来世结草衔环以报之.

阅读 1.3k
1 个回答

按照题主所给信息,原因就是“a组件进行$emit的时候b组件还没有初始化”。
具体的原理参阅并发模型与事件循环,简单说来就是 setTimeout 会把 emit事件的触发放到一个任务队列里面,等 b 组件初始化完毕再执行,因此 b 组件就可以收到了,(实际上是等整个 Vue 应用就绪再执行)。但是这样的实现其实不太稳妥,莫名其妙的延时也会让人难以琢磨。
既然 b 可以收到 a.$emit 的信息,那说明 b 是 a 的父组件,或者二者是通过 a 的父组件来通信的,这样事情就好办了, a 不需要自己生成 uuid ,uuid 由 b 生成,自己保留一份,并且传递给 a 就行了。
另外一种解决方案是手动扩展 eventBus,给它加上一个类似 FIFO 的共享队列,a 负责往里面写数据, b 负责监听其变化并从里面读数据,这样的话不论谁先谁后, uuid 都可以稳妥地传递。


PS: FIFO 可能有点装逼了,其实就是二者通过一个特定的变量传值而已:

// event.js
export const eventCenter = (() => {
    let fifo = {}, listener = {};
    
    return {
        emit(type, value){
            fifo[type] = value;
            listener[type] && listener[type].forEach(func => func(value));
        },
        on(type, callback){
            if(fifo[type]) callback(fifo[type]);
            if(listener[type]){
                listener[type].push(callback);
            } else {
                listener[type] = [callback];
            }
        }
    }
})();

// b
eventCenter.emit('uuid', 123456);

// a
eventCenter.on('uuid', console.log);

答主是个唯物主义者,不信来世,结草衔环也多余,绊不住来人的小摩托,如果答案有帮助到题主的话还请不吝采纳。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题