手写发布订阅
思路:
1、需要有一个list对象缓存订阅事件
2、订阅(on)如果存在事件就往list里面缓存事件
3、取消订阅(off)从list对象找到订阅事件删除
4、发布(emit)从list对象找到事件去执行就OK
5、只发布一次(once)执行完删除即可
class EventEmitter {
constructor(){
// 事件缓存列表
this.list = {}
}
// 订阅
on(name,fn){
// 如果存在事件
if(this.list[name]) {
this.list[name].push(fn)
} else {
this.list[name] = [fn]
}
}
// 取消订阅
off(name,fn){
// 找到已经注册的事件
let tasks = this.list[name]
// 判断该事件是否注册
if(tasks){
const index = tasks.findIndex(f === fn || f.callback === fn)
if(index>=0) {
tasks.splice(index,1)
}
}
}
// 发布
emit(name,once=false,...args){
if(this.list[name]) {
// 创建副本,如果回调函数内部继续注册相同的事件,会造成死循环
let tasks = this.list[name].slice()
for(let fn of tasks) {
fn(...args)
}
// 如果只发布订阅一次,执行完上面代码就把事件删除
if(once) {
delete this.list[name]
}
}
}
}
// 测试
let eventBus = new EventEmitter()
let fn1 = function(name, age) {
console.log(`${name} ${age}`)
}
let fn2 = function(name, age) {
console.log(`hello, ${name} ${age}`)
}
eventBus.on('aaa', fn1)
eventBus.on('aaa', fn2)
eventBus.emit('aaa', false, '布兰', 12)
网友评论