发布订阅模式在JavaScript中非常重要,可以用于模块件的通讯,DOM事件机制就是发布订阅模式的体现。接下来手动实现一个Event模块,实现以下功能
| 方法名称 | 功能 |
|---|---|
| on(event, listener) | 为指定事件添加一个监听器 |
| emit(event, [arg1], [arg2], […]) | 按监听器的顺序执行执行每个监听器,如果事件有注册监听返回 true,否则返回 false |
| once(event, listener) | 为指定事件注册一个单次监听器,即 监听器最多只会触发一次,触发后立刻解除该监听器。 |
| off(event, listener) | 移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器。 它接受两个参数,第一个是事件名称,第二个是回调函数名称。 |
| listeners(event) | 返回指定事件的监听器数组。 |
class EventEmitter {constructor() {this._eventsMap = {}}/*** 添加事件监听** @param {*} event* @param {*} listener* @param {boolean} [once=false]* @memberof EventEmitter*/on(event, listener, once = false) {if (!this._eventsMap[event]) {this._eventsMap[event] = []}const listeners = this._eventsMap[event]if (!this._eventsMap[event].includes(listener)) {this._eventsMap[event].push(listener)listener.once = once}}/*** 触发事件** @param {*} event* @param {*} args* @returns* @memberof EventEmitter*/emit(event, ...args) {const listeners = this._eventsMap[event]const _this = thisif (listeners && listeners.length > 0) {listeners.forEach(listener => {listener.call(_this, ...args)if (listener.once) {this.off(event, listener)}});return true}return false}/*** 添加事件监听,并只能触发一次** @param {*} event* @param {*} listener* @memberof EventEmitter*/once(event, listener) {this.on(event, listener, true)}/*** 取消事件监听** @param {*} event* @param {*} listener* @memberof EventEmitter*/off(event, listener) {if (this._eventsMap[event]) {if (!listener) {this._eventsMap[event] = []} else {this._eventsMap[event] = this._eventsMap[event].filter(_listener => _listener !== listener)}}}}
