求推荐可跨类全局触发事件的ES6单例EventEmitter(附示例)
推荐单例ES6 EventEmitter实现(跨类全局触发)
你要的这种无需继承、单例模式、支持跨类全局触发事件的EventEmitter,其实完全可以自己实现一个轻量版本,比找第三方工具更可控,而且完全符合你的需求。我给你写一个完整的实现和跨类使用示例:
第一步:实现单例EventEmitter
创建一个SingleTonEmitter.js文件,这里我们实现一个极简但够用的EventEmitter,并且确保它是单例:
// SingleTonEmitter.js class EventEmitter { constructor() { // 存储事件和对应的回调函数集合 this.events = new Map(); } // 监听事件 on(eventName, callback) { if (!this.events.has(eventName)) { this.events.set(eventName, []); } this.events.get(eventName).push(callback); } // 触发事件(对应你示例里的dispatch) emit(eventName, ...args) { if (this.events.has(eventName)) { this.events.get(eventName).forEach(callback => { callback(...args); }); } } // 可选:移除单个事件监听 off(eventName, callback) { if (this.events.has(eventName)) { const callbacks = this.events.get(eventName); const index = callbacks.indexOf(callback); if (index !== -1) { callbacks.splice(index, 1); // 如果该事件没有回调了,移除这个事件 if (callbacks.length === 0) { this.events.delete(eventName); } } } } // 可选:监听一次事件,触发后自动移除 once(eventName, callback) { const wrapper = (...args) => { callback(...args); this.off(eventName, wrapper); }; this.on(eventName, wrapper); } } // 导出单例实例,确保所有导入的地方用的都是同一个对象 export default new EventEmitter();
第二步:跨类使用示例
现在你可以在任何类里导入这个单例Emitter,直接使用:
监听事件的类(Listener)
// Listener.js import emitter from './SingleTonEmitter.js'; export class Listener { constructor() { // 监听'somethingHappened'事件 emitter.on('somethingHappened', (data) => { this.onChange(data); }); // 也可以用once监听一次性事件 emitter.once('oneTimeEvent', () => { console.log('这个事件只会触发一次'); }); } onChange(data) { console.log('收到事件通知,数据是:', data); // 这里写你的业务逻辑 } }
触发事件的类(DispatchClass)
// DispatchClass.js import emitter from './SingleTonEmitter.js'; export class DispatchClass { triggerEvent() { // 触发'somethingHappened'事件,并传递数据 emitter.emit('somethingHappened', { message: 'Hello from DispatchClass' }); // 触发一次性事件 emitter.emit('oneTimeEvent'); } }
测试跨类触发
// 测试代码 import { Listener } from './Listener.js'; import { DispatchClass } from './DispatchClass.js'; // 实例化监听类 const listener = new Listener(); // 实例化触发类 const dispatcher = new DispatchClass(); // 调用触发方法,Listener会收到事件 dispatcher.triggerEvent(); // 再次调用,一次性事件不会再触发 dispatcher.triggerEvent();
为什么这个方案符合你的需求?
- 单例模式:所有导入的地方用的都是同一个
EventEmitter实例,天然支持全局事件传递 - 无需继承:不需要让你的类继承EventEmitter,直接导入单例实例即可使用
- 跨类触发:Listener和DispatchClass完全独立,只要导入同一个Emitter,就能实现事件通信
- 轻量可控:你可以根据自己的需求扩展方法(比如上面的off、once),不需要引入多余的第三方依赖
如果需要更复杂的功能(比如事件命名空间、错误处理),也可以在这个基础上扩展,或者考虑使用mitt这个极小的第三方库(不过自己实现的已经完全够用大部分场景了)。
内容的提问来源于stack exchange,提问作者Patrick Teulings
相关产品推荐
相关产品推荐

