前言
发布订阅事件大家一定不陌生了,通过监听某个事件然后执行相应的操作,在Vue中,eventBus、emit、$on就是利用订阅事件来做的。说实在,个人体验最深的就是在Vue使用树形组件递归树形数据最常用了,在递归组件中使用传统的props是无法做到向父组件传递数据的,此时,订阅事件就发挥了他的作用。
实现
订阅事件是如此的强大,自己手撸一个吧。
class EventEmitter{
constructor(){
// 保留传进来的自定义事件回调函数
this.events={};
}
// 发送事件
emit(eventName,payload){
//获取自定义事件的回调事件队列
let callbackQuene=this.events[eventName];
// console.log(callbackQuene)
// 执行回调事件队列
Array.isArray(callbackQuene)&&callbackQuene.forEach(callback => {
callback.apply(this,[payload])
});
}
// 监听事件
on(eventName,callback){
// 判断自定义事件是否已注册
if(!this.events[eventName]){
this.events[eventName]=[];
};
this.events[eventName].push(callback);
}
// 卸载事件
off(eventName,callback){
// 没传参数,默认取消所有监听事件
if(typeof eventName==="undefined"){
delete this.events
}
// 取消指定事件回调
else if(typeof eventName==="string"){
// 判断事件是否已注册
if(this.events[eventName]&&Array.isArray(this.events[eventName])){
// 判断callback是否为函数
if(typeof callback==="function"){
// 过滤指定函数
this.events[eventName]=this.events[eventName].filter(cb=>cb!==callback);
}else{
this.events[eventName]=[];
}
}
}
}
// 监听一次自动后自动卸载事件
once(eventName,callback){
const onceCallback=(payload)=>{
callback.apply(this,[payload])
this.off(eventName,onceCallback)
}
this.on(eventName,onceCallback);
}
}
//实例化
const myEventEmitter=new EventEmitter();
//注册并监听事件
myEventEmitter.on('emit',(data)=>{
console.log(data)
});
setTimeout(()=>{
myEventEmitter.emit('emit','我是emit事件'); //3秒后输出
},3000);
//不传参数,取消所有事件监听
myEventEmitter.off();
//传参数与不传回调函数,取消指定事件的所有回调函数
myEventEmitter.off('emit');
//传参数与取消指定回调函数
myEventEmitter.off('emit',(data)=>{
console.log(data)
});
//只执行一次回调函数
myEventEmitter.once('once',(data)=>{
console.log('once')
})
setTimeout(()=>{
myEventEmitter.emit('once',{});//3秒后输出once
},3000);
setTimeout(()=>{
myEventEmitter.emit('once');//不再输出once
console.log(66)
},5000)
结语
手动实现还是挺简单的,各位也可以自己手撸一个,加深理解,毕竟好记性不如烂笔头。哎呀,头发又掉了好几根......