You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

是否有纯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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:10:38