发布 / 订阅
看起来貌似用数组可以实现,先来试一下
let event={
list:[],
on(fn){
if(this.list.includes(fn))return false
this.list.push(fn)
},
emit(){
this.list.forEach(cb=>{
cb()
})
}
}
function log(){
console.log('log')
}
event.on(log)
event.emit(log)
看起来没有问题,但是好像和我们平时使用的不一样呀,应该有事件名,而且按照以上的写法,会执行所有被监听的函数,而不是我们想要触发的事件,改写一下
想要修复以上缺点,就不能用数组来存储,要使用对象
let event={
list:{},
on(name,fn){
if(!this.list[name]){
this.list[name]=[]
}
this.list[name].push(fn)
},
emit(){
let args=[...arguments]
let name=args.shift()
let fns=this.list[name]
fns.forEach(cb=>{
cb.apply(null,args)
})
}
}
function log(eventName){
console.log(eventName)
}
function log2(eventName){
console.log(eventName)
}
event.on('print',log)
event.on('print2',log2)
event.emit('print','print')
event.emit('print2','print2')
这样就可以正常工作啦,每个事件互不影响,因为回调函数存储在不同的数组
新增一个取消订阅的方法
let event={
list:{},
on(name,fn){
if(!this.list[name]){
this.list[name]=[]
}
this.list[name].push(fn)
},
emit(){
let args=[...arguments]
let name=args.shift()
let fns=this.list[name]
if(!fns||fns.length===0)return false
fns.forEach(cb=>{
cb.apply(null,args)
})
},
remove(name,fn){
let fns=this.list[name]
if(!fns)return false
if(!fn){
fns.length=0
return
}
fns.forEach((cb,i)=>{
if(cb===fn){
fns.splice(i,1)
}
})
return true
}
}
function log(eventName){
console.log(eventName)
}
function log2(eventName){
console.log(eventName)
}
event.on('print',log)
event.on('print2',log2)
event.remove('print2')
event.emit('print','print')
event.emit('print2','print2')