Vue之全局事件总线和消息订阅与发布

之前我们实现了子组件向父组件传递数据,很明显,这是不够的,看完这篇博客,无论哪两个组件之间传递和接收数据都没有问题!

 

全局事件总线(适用于任意组件间通信)

原理:(看图理解)

主要就是通过往 x 身上放事件,然后事件的回调要放在想要获取数据的组件身上,谁要传数据就调用 x 身上对应的事件并往里面存数据就可以了,相当于一个中间商(哎,不得不说,它一出生就被利用了)

当然不是谁都能但此大任的,x 需要具备两个条件:

1. 所有组件都可以看到

2. x 身上有 $on 、$off 、$emit 方法

统一给 x 命名为 $bus

我们将其定义在 main.js 文件中,创建在 vm 的实例对象身上,因为 vm 实例对象只有一个

创建全局事件总线有两种方法:

1. const Demo = Vue.extend({})

    const d = new Demo()

    Vue.prototype.$bus = d

   (定义在创建 Vue 的外面)

2. new Vue({

     ......

     beforeCreate(){

     Vue.prototype.$bus = this //安装全局事件总线, $bus 就是当前应用的 vm

},

})

new Vue({
  render: h => h(App),
  beforeCreate(){
    Vue.prototype.$bus = this  //安装全局事件总线
  }
}).$mount('#app')

使用事件总线:

1. 接收数据:A 组件想接收数据,则在 A 组件中给 $bus 绑定自定义事件,事件的回调留在 A 组件自身

  mounted() {
    //或者后面指向的是一个方法,方法在 methods 里面定义
    //在全局事件总线 $bus 中绑定一个 hello 事件,后面的回调是箭头函数,用于接收数据
    this.$bus.$on("hello", (value) => {
      console.log("我获取到了数据", value);
    });
  },

2. 提供数据:

  methods: {
    sentMyName(){
      //在该方法中触发 hello 这个事件,把数据传过去
      this.$bus.$emit('hello',this.myName)
    }
  },

用这个方法的好处就是!我们就不需要再在标签里绑定自定义事件了,直接把事件在 $bus 里创建,再在要传数据的地方调用它就可以了!

当然还有个注意点,如果某个事件或绑定事件的组件你不用了,那要养成随时解绑的好习惯!不要占着空间不用,会导致空间浪费从而出现卡顿

最好在 beforeDestroy 钩子中,用 $off 去解绑当前组件所用到的事件

在绑定事件的组件中解绑(即需要数据的组件)

  beforeDestroy() {
    //解绑 $bus 中 名为 hello 的事件
    this.$bus.$off("hello");
  },

切记!this.$bus.$off() 里面一定要写要解绑的事件,不然 $bus 中所有的事件都会被解绑!后果很严重!!!!

消息订阅与发布(适用于任意组件间通信)

原理:

简单理解:

需要数据的组件:订阅消息
提供数据的组件:发布消息 

这个相比第一种方法就要麻烦那么一丢丢了,它需要安装 pubsub,我们打开 VScode 的控制台,输入 npm i pubsub-js,进行安装

在传数据和接收数据的组件中都要通过 import pubsub from 'pubsub-js' 引入这个文件

然后就可以开始使用了

接收数据:A 组件想接收数据,则在 A 组件中订阅消息,订阅的回调留在 A 组件自身

    this.pubId = pubsub.subscribe('hello',(msgName,data)=>{
      console.log('我接收到数据了',data);
    })

这里有一个注意点,那就是回调函数的第一个参数 msgName,代表的是 hello,即订阅的消息名,这个必须要写,因为默认第一个参数就是消息名,第二个参数才是数据,所以不管如何,第一个要占个位,你可以给它取个名字,或者用下划线 _ 占位

提供数据:

  methods: {
    sentMyName(){
      pubsub.publish('hello',this.myName)
    }
  },

当然如果订阅的消息不用了,也要将其删除,不能占用空间,但是删除订阅消息不是用 $off ,而是 publish.unsubscribe(this.pubId),其中 this.pubId 是每个消息创建的时候都会有一个 id,就像定时器一样,我们删除就删除它对应的 id 号就可以了

  beforeDestroy() {
    pubsub.unsubscribe(this.pubId)
  },

 对比两者我们用的更多的是前者,因为它是 Vm 里面创建的,不需要再导入包


最后再分享一个方法:

 

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
)">
下一篇>>