观察者模式的简单理解:
> 就比如小时候的一个游戏“打地鼠”,我们作为观察者,地鼠是被观察者,当地鼠露出头的这个行为,我们会去做一件事情,就是去敲它。
观察者模式在前端运用的非常多,比如浏览器的事件流程、vue中的v-model,子父组件的通信,eventBus、node的内置模块events
其主要的作用是解决对象与对象之间的耦合
下面我们手动简单实现一个eventEmitter
直接上代码:
function EventEmitter () {
this._events = new Map() // 存储事件监听的对象
this.maxEventListener = 5 // 监听上限
}
// 添加事件监听
EventEmitter.prototype.on = function (eventType, callback) {
const events = this._events.get(eventType)
if (events && events.length >= this.maxEventListener) {
throw Error('已到达事件监听数量的上限')
}
events || this._events.set(eventType, [])
this._events.get(eventType).push(callback)
}
// 触发事件
EventEmitter.prototype.emit = function (eventType, ...args) {
const events = this._events.get(eventType)
if (events && events.length) {
events.forEach(fn => {
fn(...args)
})
}
}
// 移除监听的事件
EventEmitter.prototype.off = function (eventType, fn) {
let events = this._events.get(eventType)
if (!events) return false
if (fn) { // 如果传入了fn,删除eventType对应数组里面指定的fn
let index = events.findIndex(item => item === fn)
if (index > -1) {
events.splice(index, 1)
return true
}
return false
} else {//如果没有传fn,则删除_events里面的eventType
this._events.delete(eventType)
return true
}
}
// 监听事件,但只触发一次
EventEmitter.prototype.once = function (eventType, callback) {
const _this = this
function fn () {
callback.apply(null, [...arguments])
_this.off(eventType, fn)
}
this.on(eventType, fn)
}
// 设置监听上限
EventEmitter.prototype.setMaxEventListener = function (n) {
this.maxEventListener = n
}
const obsever = new EventEmitter()
const foo = function () {
console.log('foo')
}
obsever.on('click', (params) => {
console.log('触发click',params)
})
obsever.on('change', () => console.log('触发change'))
obsever.on('change', foo)
obsever.once('change', ()=>console.log('once'))
obsever.emit('click','params')
obsever.emit('change')
obsever.off('change', foo)
obsever.emit('change')
// 触发click params
// 触发change
// foo
// once
// 触发change