写点什么

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

作者:编程江湖
  • 2021 年 12 月 14 日
  • 本文字数:1668 字

    阅读完需:约 5 分钟

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

全局事件总线(适用于任意组件间通信)原理:(看图理解)



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

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

  1. 所有组件都可以看到

  2. x 身上有 on、on 、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 中绑定一个 hello 事件,后面的回调是箭头函数,用于接收数据 this.bus 中绑定一个 hello 事件,后面的回调是箭头函数,用于接收数据 this.bus.$on("hello", (value) => {console.log("我获取到了数据", value);});},

  1. 提供数据:

methods: {sentMyName(){//在该方法中触发 hello 这个事件,把数据传过去 this.bus.bus.bus.emit('hello',this.myName)}},用这个方法的好处就是!我们就不需要再在标签里绑定自定义事件了,直接把事件在 $bus 里创建,再在要传数据的地方调用它就可以了!

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

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

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

beforeDestroy() {//解绑 bus 中名为 hello 的事件 this.bus 中 名为 hello 的事件 this.bus 中名为 hello 的事件 this.bus.off("hello"); }, 切记!this.bus.off()里面一定要写要解绑的事件,不然 off() 里面一定要写要解绑的事件,不然 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 里面创建的,不需要再导入包

最后再分享一个方法:



用户头像

编程江湖

关注

IT技术分享 2021.11.23 加入

还未添加个人简介

评论

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