方法名 | 方法描述 |
addListener(event, listener) | 为指定事件添加一个监听器到监听器数组的尾部。 |
prependListener(event,listener) | 与addListener相对,为指定事件添加一个监听器到监听器数组的头部。 |
on(event, listener) | 其实就是addListener的别名 |
once(event, listener) | 为指定事件注册一个单次监听器,即 监听器最多只会触发一次,触发后立刻解除该监听器。 |
removeListener(event, listener) | 移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器 |
off(event, listener) | removeListener的别名 |
removeAllListeners([event]) | 移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器。 |
setMaxListeners(n) | 默认情况下, EventEmitters 如果你添加的监听器超过 10 个就会输出警告信息。 setMaxListeners 函数用于提高监听器的默认限制的数量。 |
listeners(event) | 返回指定事件的监听器数组。 |
emit(event, [arg1], [arg2], [...]) | 按参数的顺序执行每个监听器,如果事件有注册监听返回 true,否则返回 false。 |
每一个EventEmitter实例都有一个包含所有事件的对象_events, 事件的监听和监听事件的触发,以及监听事件的移除等都在这个对象_events的基础上实现。
首先实现一个EventEmitter类
class EventEmitter { constructor() { this._events = Object.create(null); // 定义事件的存储对象 this._eventsCount = 0; } }接着实现添加事件监听的on方法:
- 为每个事件名称添加一个数组作为事件的存储器
- 事件由一个对象来保存,为了区别开on和once需要为每个事件增加一个isOnce字段
//添加事件监听 on(eventName, fn, isOnce = false) { if (typeof fn !== "function") { throw new TypeError("The listener must be a function!"); } if (!this._events[eventName]) { this._events[eventName] = []; this._events[eventName].push({ fn, isOnce }); } else { this._events[eventName].push({ fn, isOnce }); // 存入监听的事件名和事件 } }实现事件触发方法emit:
- 找到事件名称下面的所有事件以此触发
- 当事件的isOnce 为true的时候在触发事件之后清空事件
// 事件触发 emit(eventName, ...args) { if (!this._events[eventName]) { return false; } const len = this._events[eventName].length; for (let i = 0; i < len; i++) { let event = this._events[eventName][i]; event.fn.call(this, ...args); if (event.isOnce) { this.removeListener(eventName, event.fn); i--; } } }
事件监听解绑 1.清空事件名下的监听的函数,函数为undefined则清空事件名下所有事件
// 移除监听事件 removeListener(eventName, fn) { if (!this._events[eventName]) return this; if (!fn) { delete this._events[eventName]; return this; } else { this._events[eventName].forEach((item, index) => { if (item.fn === fn) { this._events[eventName].splice(index, 1); } else { return this; } }); } }
全部代码实现
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>手动实现一个eventEmitter</title> </head> <body> <script> class EventEmitter { constructor() { this._events = Object.create(null); // 定义事件的存储对象 this._eventsCount = 0; } //添加事件监听 on(eventName, fn, isOnce = false) { if (typeof fn !== "function") { throw new TypeError("The listener must be a function!"); } if (!this._events[eventName]) { this._events[eventName] = []; this._events[eventName].push({ fn, isOnce }); } else { this._events[eventName].push({ fn, isOnce }); // 存入监听的事件名和事件 } } //一次性事件监听 once(eventName, fn) { this.on(eventName, fn, true); } // 事件触发 emit(eventName, ...args) { if (!this._events[eventName]) { return false; } const len = this._events[eventName].length; for (let i = 0; i < len; i++) { let event = this._events[eventName][i]; event.fn.call(this, ...args); if (event.isOnce) { this.removeListener(eventName, event.fn); i--; } } } // 移除监听事件 removeListener(eventName, fn) { if (!this._events[eventName]) return this; if (!fn) { delete this._events[eventName]; return this; } else { this._events[eventName].forEach((item, index) => { if (item.fn === fn) { this._events[eventName].splice(index, 1); } else { return this; } }); } } // off:removeListener 的别名 off(eventName, fn) { this.removeListener(eventName, fn); } // 移除所有监听事件 removeAllListener(eventName) { if (eventName) { if (this._events[eventName]) { this._events[eventName].length = 0; } } else { this._events = Object.create(null); } } } function add(...args) { let num = 0; for (let i = 0; i < args.length; i++) { num += args[i]; } console.log(num); return num; } let event = new EventEmitter(); // event.on("adding", add); // event.emit("adding", 1, 2, 3, 4); // event.removeListener("adding", add); // event.emit("adding", 1, 2, 3, 4); // event.once("adding", add); event.emit("adding", 1, 2, 3, 4); event.emit("adding", 1, 2, 3, 4); </script> </body> </html>