vue 组件通过bus通讯疑问

ishowman
  • 268

1.问题

  • 是否非父子非兄弟关系的组件不能通过bus通讯?请各位大佬赐教解疑
  • 这个问题的 目的是更深入理解bus 的过程产生的,请 不要说用vuex

2.代码思路

  • 在路由中注册a组件,b组件
  • 在bus.js创建空的 Vue 实例作为事件总线
  • 访问a组件的页面: /aaa。然后点击按钮,通过bus派发事件
  • 在b组件中监听bus的自定义事件。但在a组件中派发事件后再访问b组件,b组件的监听函数未执行

如没能看懂,拜托复制相关代码在本地跑下

3.相关代码(基于vue-cli)

组件a

    <template>
      <div>
          组件a
          <button @click="sendMsg">问候组件b</button>
      </div>
    </template>
    <script>
    import bus from './bus'
    export default {
        methods: {
            sendMsg() {
                bus.$emit('send', '组件b你好吗?')
                this.$router.push('/bbb')
            }
        }
    }
    </script>

组件b

<template>
    <div>
        <p>组件b:{{ msg }}</p>
    </div>
</template>
<script type="text/javascript">
import  bus  from './bus'
export default {
    data () {
        return {
            msg: 'msg初始值'
        }
    },
    mounted () {
        bus.$on('send', data => {
            console.log(data)
            console.log(this)
            this.msg = data
        })    
    } 
  
}
</script>

bus.js

import Vue from 'vue';
export default new Vue()

路由

const aaa = () => import('@/components/zujian/bus/a')
const bbb = () => import('@/components/zujian/bus/b')
export default new Router({
  routes: [{
      path: '/aaa',
      component: aaa
    },
    {
      path: '/bbb',
      component: bbb
    }]
})
回复
阅读 3.5k
7 个回答

其实了解一下底层原理就明白了,实际上就是运用了Vue内部的事件机制,可以参考Vue事件机制

emit做的事情就是从事件队列中找到对应的事件并执行,找不到则会丢弃,所以需要保证在此之前已经用on注册了事件。

题主这段代码组件B中的on还没执行过就已经调用了组件A的emit了。

Danjy
  • 221

eventbus可以实现 非父子关系的组件之间的通信. 前提是两个组件都已经调用过mouted钩子.也就是a / b页面都进入(渲染)过.

bus的出现就是为了解决非父子组件之间的通信的,而你也说过bus是通过创建空的 Vue 实例作为事件总线来传递信息 的,所以:非父子非兄弟关系的组件都能通过bus通讯;
你这个代码的问题:
当你问候组件b的时候路由还没转跳,也就是组件b还没有实例化(渲染),就好比只有打电话的,但接电话的都没有电话,那别人怎么知道你有没有给我打电话?所以,完成不了通信
有问题继续来问,希望帮到你

可以参考一下我写的文章哦,里面就是关于bus通信的,挺详细的,不懂可以问一下

事件总线当然可以,不过要保证先绑定事件再触发事件,这种模式容易造成代码逻辑混乱。

可以通过打印生命周期方法来知道为什么msg没有更新

你在A执行emit的地方
B beforeCreate
B created
B beforeMount
A beforeDestroy
A destroyed
你在B执行on的地方
B mounted

可以看到vue-router在切换路由时的状态变化,将on放到emit之前即可