是否有纯HTML5/JavaScript替代jQuery.Callbacks()实现客户端发布订阅?
替代jQuery.Callbacks()的发布订阅方案
嘿,这个问题问到点子上了!就像fetch替代$.ajax()一样,现在确实有不少无需依赖jQuery的方案,能实现和jQuery.Callbacks()一样的发布订阅(Pub/Sub)功能,甚至更轻量灵活。下面给你梳理几个常用的选项:
1. 自己实现极简版Pub/Sub
jQuery.Callbacks()的核心逻辑其实就是管理回调队列,自己写一个也很简单,完全可控,还能根据需求定制功能。比如:
const PubSub = { // 用Map存储事件名对应的回调数组 _events: new Map(), // 订阅事件,返回取消订阅的函数 subscribe(eventName, callback) { if (!this._events.has(eventName)) { this._events.set(eventName, []); } this._events.get(eventName).push(callback); return () => { 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); } } }; }, // 发布事件,支持传递任意参数 publish(eventName, ...args) { const callbacks = this._events.get(eventName) || []; callbacks.forEach(callback => callback(...args)); }, // 可选:清空某个事件的所有订阅 clear(eventName) { this._events.delete(eventName); } }; // 使用示例 const unsubscribe = PubSub.subscribe('orderPlaced', (orderId) => { console.log(`订单 ${orderId} 已创建,开始处理`); }); PubSub.publish('orderPlaced', '12345'); // 输出: 订单 12345 已创建,开始处理 unsubscribe(); // 取消该订阅 PubSub.clear('orderPlaced'); // 清空该事件的所有订阅
2. 利用浏览器原生的EventTarget
浏览器的EventTarget接口是DOM事件的基础,其实我们可以直接用它来做非DOM场景的发布订阅,不用自己维护回调队列,原生API稳定可靠:
// 继承EventTarget实现自定义发布订阅类 class PubSub extends EventTarget { publish(eventName, data) { // 用CustomEvent携带数据 this.dispatchEvent(new CustomEvent(eventName, { detail: data })); } } // 使用示例 const appPubSub = new PubSub(); const handleUserLogin = (e) => { console.log(`用户 ${e.detail.username} 登录成功`); }; // 订阅事件 appPubSub.addEventListener('userLogin', handleUserLogin); // 发布事件 appPubSub.publish('userLogin', { username: 'dacracot' }); // 取消订阅 appPubSub.removeEventListener('userLogin', handleUserLogin);
这个方案的优势是完全原生,无需额外代码,兼容性也很好(除了IE11及以下)。
3. 轻量第三方库
如果不想自己写,也可以用专门的轻量Pub/Sub库,体积通常只有几KB甚至几百字节,功能比jQuery.Callbacks()更丰富:
比如mitt(目前很流行的极简事件发射器):
import mitt from 'mitt'; const emitter = mitt(); // 订阅单个事件 emitter.on('messageReceived', (msg) => { console.log(`收到消息:${msg.content}`); }); // 订阅所有事件 emitter.on('*', (eventName, msg) => { console.log(`事件 ${eventName} 触发,数据:`, msg); }); // 发布事件 emitter.emit('messageReceived', { content: 'Hello World!' }); // 取消单个订阅 emitter.off('messageReceived'); // 清空所有订阅 emitter.all.clear();
还有tiny-emitter,API和jQuery更接近,上手快:
import Emitter from 'tiny-emitter'; const emitter = new Emitter(); emitter.on('alert', (text) => { console.log(`提示:${text}`); }); emitter.emit('alert', '请填写完整信息'); emitter.off('alert');
总结
这些方案都能完美替代jQuery.Callbacks():
- 自己实现:最灵活,可按需扩展功能,无任何依赖
EventTarget:原生API,稳定省心,适合简单场景- 轻量库:开箱即用,功能完善,体积远小于jQuery
内容的提问来源于stack exchange,提问作者dacracot
相关产品推荐
相关产品推荐

