目录
一、概念
二、手写
1. 代码
2. 栗子
三、Vue2 中
1. 在 main.js 中注册
2. 在某组件发射事件
3. 在某组件监听事件
4. 移除事件
四、Vue3 中
1. 安装
2. 封装一下
3. 发射事件
4. 监听事件
5. 取消事件
事件总线也是一种通信方式,只不过它的功能比较强大,不在局限于父传子或兄弟组件之间通信,它可以跨组件通信,通过事件总线传递的值,不管哪个组件都可以获取到
总而言之,可以在各个模块中通信并且传递数据
事件总线属于一种观察者模式,其中包括三个角色 :
class StarEventBus {
constructor() {
// 事件名称 和 方法的映射关系
this.eventMap = {};
}
/**
* 监听
* 因为可能有相同的名字监听,但是回调函数不一样
* 所以使用数组存储
*/
on(eventName, fn) {
if (!this.eventMap[eventName]) {
this.eventMap[eventName] = [];
}
this.eventMap[eventName].push(fn);
}
/**
* 发射事件
* 一发射就自动调用方法
*/
emit(eventName, ...args) {
if (!this.eventMap[eventName]) return;
this.eventMap[eventName].forEach((fn) => {
fn(...args);
});
}
/**
* 删除事件
* 删除事件名和其对应的函数
*/
off(eventName, fn) {
if (!this.eventMap[eventName]) return;
// 可能拥有相同的事件名和相同的函数,所以循环删除
this.eventMap[eventName].forEach((itemFn, index) => {
if (itemFn === fn) {
// 使其位置还在,不过是为空
delete this.eventMap[eventName][index];
}
});
// 过滤空的值
this.eventMap[eventName] = this.eventMap[eventName].filter((item) => item);
// 如果eventFns已经清空了
if (this.eventMap[eventName].length === 0) {
delete this.eventMap[eventName];
}
}
/**
* 清空事件名对应的事件函数数组
*/
clear(eventName) {
if (!this.eventMap[eventName]) return;
delete this.eventMap[eventName];
}
/**
* 清空所有事件
*/
clearAll() {
this.eventMap = {};
}
}
// 1. 创建对象
const eventBus = new StarEventBus();
// 2. 监听方法
eventBus.on('btnClick', () => {
console.log('俺被惦记了');
});
const btnClick = () => {
console.log('俺也被惦记了');
};
eventBus.on('btnClick', btnClick);
setTimeout(() => {
// 4. 删除方法
eventBus.off('btnClick', btnClick);
}, 3000);
const btnDom = document.querySelector('button');
btnDom.onclick = function () {
console.log('btn 点击');
// 3. 发射方法
eventBus.emit('btnClick');
};
Vue2默认是带有事件总线的功能,因为vue实例自带了以下方法
// 在入口 main.js 中,创建一个 bus 总线,这样全局都可以使用
Vue.prototype.$bus = new Vue()
zhong
// 取消所有的事件监听
emitter.all.clear()
// 取消指定事件监听,方法要使用同一个 如 : sonEmit.
function onFoo(){}
emitter.on('sonEmit', onFoo)
emitter.off('sonEmit', onFoo)