一、什么是EventBus
- EventBus是一个开源库,利用发布/订阅者模式对项目进行解耦
- 利用很少的代码来实现多组件间通信
- 在Vue中可以使用它来作为沟通桥梁的概念,就像所有组件共用的相同的事件中心
- 如图所示,可以向该中心注册发送事件或者接收事件,这也就说明了所有组件可以上下平行地通知其他组件
二、 在vue2 中如何使用eventBus
🌼 创建事件总线
- 第一种方法是可以直接在
main.js
初始化,在vue的原型对象上定义$eventBus
javascript
//main.js
Vue.prototype.$eventBus = new Vue()
- 第二种可以新建一个.js文件,在其中引入Vue并导出它的一个实例
javascript
//event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()
实质上它算一个不具备DOM的组件,我们需要的仅仅是它的实例方法
🌼 引入event-bus.js
- 仅使用上述第二种方法才需要这一步
- 每一个使用到eventBus的组件都需要引入event-bus.js
javascript
import EventBus form './eventBus.js'
🌼触发事件
- 发布者角色
- 使用方法
javascript
//对于方式一
this.$eventBus.$emit('eventName',params....)
//对于方式二
EventBus.$emit('eventName',params....)
- 使用实例 --在页面A发布事件
<template>
<button @click="sendMsg()">-</button>
</template>
<script>
import EventBus from './eventBus.js'
export default {
methods: {
//发送事件
sendMsg() {
EventBus.$emit("aPostMsg", '页面A发出的消息');
//或者
this.$eventBus.$emit('aPostMsg','页面A发出的消息');
}
}
};
🌼 监听事件
- 订阅者角色
- 使用方法
//对于方式一
this.$eventBus.$on('evnetName',(params...) => {
//do something....
})
//对于方式二
EventBus.$on('eventName', (params...) => {
//do something....
})
- 使用实例 --在页面B订阅事件
<script>
import EventBus from './eventBus.js'
export default {
data(){
return {}
},
mounted() {
EventBus.$on("aPostMsg", (msg) => {
console.log(msg) //页面A发出的消息
});
//或者
this.$eventBus.$on("aPostMsg", (msg) => {
console.log(msg) //页面A发出的消息
});
}
};
如果只是这样的,监听事件会一直存在,反复进入到接收组件内操作获取数据我们只期待发送一次,但是会发生多次
🌼 移除事件监听
原因:
- 避免在监听的时候,如上述所说的,事件被反复监听
- 因为是热更新,事件可能会被多次绑定监听
- 没有及时移除eventBus也可能会导致内容泄漏
那么如何移除事件监听呢
- 移除单个事件
//对于方式一 EventBus.$off('aPostMsg') //对于方式二 this.$eventBus.$off('aPostMsg')
- 移除所有事件
//对于方式一 EventBus.$off('aPostMsg') //对于方式二 this.$eventBus.$off('aPostMsg')
使用实例
- 在beforeDestroyed(){}中监听移除事件
beforeDestroyed(){ EventBus.$off('aPostMsg') //或者 this.$eventBus.$off('aPostMsg') }
三、vue3 中的 eventBus
🌷 Vue3的变化
- 在 Vue3.0+ 的版本中,Vue 移除了
$on
、$off
和$once
方法;并且没有提供兼容的功能 - 在vue3中推荐我们使用
mitt
事件总线传递数据,其实mitt的使用方式和vue原本的自定义事件使用方式相同 -详细可查看文档
🌷 mitt的使用
- 在根目录终端执行
```js
npm install --save mitt
```
- 将方法导出使用
```js
// eventBus.js
import emitter from 'tiny-emitter/instance'
export default {
$on: (...args) => emitter.on(...args),
$once: (...args) => emitter.once(...args),
$off: (...args) => emitter.off(...args),
$emit: (...args) => emitter.emit(...args),
}
```
四、 手写 eventBus
🌻 实现思路:
- 声明了一个
EventBus
类,用来处理发布订阅,用events
对象存储监听的时间, 用数组存储监听事件的回调函数 - 订阅 了事件thing1,thing2.... 先判断该事件是否存储过,如果没有存储过就赋值为空数组,存储过就往数组里面
push
回调函数 - 触发了事件,则从
events
取出该事件的回调函数数组,利用for..of..对其进行遍历调用 - 移除事件 ,如果events有该事件的话则对其进行delete
🌻 实现代码
class EventBus {
constructor() {
this.events = {}; // 用于存储所有订阅事件
}
// 订阅事件
$on(name, callbcak) {
// 判断是否存储过
if(!this.events[name]) {
this.events[name] = [];
}
this.events[name].push(callbcak); // 往事件数组里面push
}
// 发布事件
$emit(name, ...args) {
// 获取存储的事件回调函数数组
const eventList = this.events[name];
// 执行所有回调函数
for (const callbcak of eventList) {
callbcak(...args);
}
}
// 移除事件
$off(name) {
if(this.evetns[name]) {
delete this.events[name]
}