开源项目
bit-event:一个零依赖的全局事件系统,模块解耦全靠它
零依赖的轻量事件系统,支持按 ID、名称、目标对象批量移除监听,提供全局单例和独立实例两种用法,适合模块间解耦通信。
bit-event:一个零依赖的全局事件系统,模块解耦全靠它
它解决什么问题
模块之间互相调用,最开始图省事直接 import 对方然后调方法,写着写着就变成了一张互相纠缠的依赖网——UI 模块 import 了战斗模块,战斗模块又 import 了 UI 模块,改一个地方不知道会牵动多远。事件系统是解这个问题最常见的办法:谁也不认识谁,只通过事件名义广播,听的人自己决定接不接。
bit-event 是 bit-framework 里最基础的一个模块,零依赖,纯 TypeScript 实现,bit-ec 就是拿它做组件间通信的。
安装
npm install @gongxh/bit-event
核心用法
全局事件
import { GlobalEvent } from '@gongxh/bit-event';
// 监听
const id = GlobalEvent.add('mail:new', (mailId: number) => {
console.log('收到新邮件', mailId);
}, this);
// 发送
GlobalEvent.send('mail:new', 1001);
// 只听一次,触发后自动移除,不用手动清理
GlobalEvent.addOnce('game:firstLogin', onFirstLogin);
移除监听,四种方式挑一种
GlobalEvent.remove(id); // 按具体的监听 ID
GlobalEvent.removeByName('mail:new'); // 这个事件名的所有监听都移除
GlobalEvent.removeByTarget(this); // 这个 target 挂的所有监听都移除
GlobalEvent.removeByNameAndTarget('mail:new', this); // 精确匹配名字+target
实际项目里用得最多的是 removeByTarget——组件销毁的时候,一句话把它注册过的所有监听清空,不用一个个记 ID:
onDestroy(): void {
GlobalEvent.removeByTarget(this);
}
需要隔离的场景,自己 new 一个
如果某个子系统的事件不想跟全局事件混在一起(比如一个可以整体重置的小游戏内小游戏),创建独立实例,API 跟全局事件完全一样:
import { EventManager } from '@gongxh/bit-event';
class MiniGameContext {
event = new EventManager();
}
// 退出小游戏时一次清空,不影响全局事件系统
miniGameContext.event.clearAll();
最佳实践
事件名建议用常量集中管理,别在业务代码里到处写字符串字面量,拼错一个字母编译期是发现不了的,只有运行时才会发现监听没触发。
// events.ts 集中定义
export const GameEvents = {
MailNew: 'mail:new',
FirstLogin: 'game:firstLogin',
} as const;
另外要小心事件循环:事件 A 的回调里发了事件 B,事件 B 的回调里又发了事件 A,这种链路在代码量小的时候看不出来,模块一多很容易绕出一个死循环,排查起来要一路顺着监听关系摸,比较费时间。
避坑提醒
- 忘记在对象销毁时移除监听,是这类事件系统最常见的内存泄漏来源——已经销毁的对象的回调函数还挂在事件表里,事件一发送就会尝试调用一个”死对象”上的方法。养成
onDestroy里removeByTarget(this)的习惯基本能规避。 send和sendToTarget的区别别搞混:send是广播给所有监听这个名字的人,sendToTarget只发给指定的那个 target,其他监听同名事件的人收不到。- 需要能整体清空、跟全局事件互不干扰的场景,直接用独立的
EventManager实例,不要把这类临时性、局部性的事件也塞进全局事件里,退出的时候不好统一清理。
项目信息
- GitHub: https://github.com/gongxh0901/bit-framework/tree/main/bit-event
- npm: @gongxh/bit-event
- 许可证: MIT License
bit-ec 用它做组件间通信,是目前唯一把它当 peer 依赖的模块,但它本身完全独立,任何 TypeScript 项目都能直接拿去用,不限定 Cocos Creator。