前言: 单页面应用,页面不刷新,页面定义的变量和函数是一直保持的。
vue中的全局事件总线,是把触发的回调方法挂到了vue全局变量上。先监听,然后在需要的地方触发。因为全局变量,子孙组件通过引用都可以访问到。
简单理解为,提前把要触发方法先保存起来,在使用的地方传参调用
先定义一个类,初始化保存我们要执行的函数
class Bus{
constructor(){
this.eventPool = {};
};
};
模式实现 $on 方法,将监听的函数保存到 eventPool 属性上
on(eventName, cd){
if ( typeof cd === 'function'){
this.eventPool[eventName] = cd;
console.log('监听了一个事件:', eventName);
} else {
console.log('请设置监听回调函数');
}
};
模拟实现 off 方法, 删除之前保存的函数
off(...argem){
Array.from(argem).forEach((eventName) => {
delete this.eventPool[eventName];
console.log('卸载了一个事件:', eventName);
});
};
模拟实现 emit 方法,这个方法就是触发器,通过指定的函数名去找应的函数执行,同时将参数传递过去。
emit(...agemt){
const eventName = agemt[0];
const cd = this.eventPool[eventName];
const paramenter = agemt.slice(1);
if (typeof cd === 'function') {
cd(...paramenter);
console.log('触发了一个事件:', eventName);
};
};
基本实现了,测试一下。
const myBus = new Bus();
myBus.on('loading', (res) => {
console.log(res);
})
myBus.on('loadEnd', (res) => {
console.log(res);
})
setTimeout(() => {
myBus.emit('loading', '数据加载中');
setTimeout(() => {
myBus.emit('loadEnd', '数据加载完毕');
myBus.off('loading', 'loadEnd');
}, 2000)
}, 2000);
测试结果与预期相同

实现代码
class Bus{
constructor(){
this.eventPool = {};
}
on(eventName, cd){
if ( typeof cd === 'function'){
this.eventPool[eventName] = cd;
console.log('监听了一个事件:', eventName);
} else {
console.log('请设置监听回调');
}
};
off(...argem){
Array.from(argem).forEach((eventName) => {
delete this.eventPool[eventName];
console.log('卸载了一个事件:', eventName);
})
}
emit(...agemt){
const eventName = agemt[0];
const cd = this.eventPool[eventName];
const paramenter = agemt.slice(1);
if (typeof cd === 'function') {
cd(...paramenter);
console.log('触发了一个事件:', eventName);
}
}
}
总结: 在框架中要比这复杂的多,如果项目庞大,对于事件的命名,可以更据场景命名。避免冲突。