简介: 观察者模式或者说订阅模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。
通俗来说,就像订报纸一样,只要你订阅了这个报纸,当新报发布的时候你就会收到新报纸的推送。许多场景都运用了这种订阅模式,如vue.$on
、vue.$emit
;Node
中的EventEmitter
等。
其实现也是相对来说比较简单的,废话不多说,直接上代码
class Event {
constructor() {
this.handlers = {}
}
on(eventName, cb) {
const eventCallbackStack = this._getHandler(eventName).callbackStack
eventCallbackStack.push(cb)
}
emit(eventName, ...args) {
if(this.handlers[eventName]) {
this.handlers[eventName].callbackStack.forEach(cb => {
// 修正this指向
cb.call(cb, ...args)
})
// 移除once事件
if(this.handlers[eventName].isOnce) {
this.off(eventName)
}
}
}
off(eventName) {
this.handlers[eventName] && delete this.handlers[eventName]
}
once(eventName, cb) {
const eventCallbackStack = this._getHandler(eventName, true).callbackStack
eventCallbackStack.push(cb)
}
/**
* 根据事件名获取事件对象
* @param eventName
* @param isOnce // 是否为once事件
*/
_getHandler(eventName, isOnce = false){
if(!this.handlers[eventName]) {
this.handlers[eventName] = {
isOnce,
callbackStack: [],
}
}
return this.handlers[eventName]
}
}
- 测试
on
事件
const event = new Event()
console.log('注册listen事件')
event.on('listen', function(a, b){
console.log('监听到listen事件:', a, b)
})
console.log('触发listen事件')
event.emit('listen', 1, 2)
console.log('注销listen事件')
event.off('listen')
console.log('再次触发listen事件')
event.emit('listen', 1, 2)
可以看到on
事件是可以off
注销掉的,注销之后就没有再次触发了
- 测试
once
事件
console.log('注册once事件')
event.once('once', function (a,b) {
console.log('监听到once事件:',a, b)
})
console.log('触发once事件')
event.emit('once', 1, 2)
console.log('再次触发once事件')
event.emit('once', 1, 2)
可以看到once
事件只触发一次