mitt@3.0.1发布日期: 2023年7月5日
mitt 是一个超轻量(约 200 字节)、无依赖的 JavaScript 事件发射器 / 事件总线库,核心作用是实现发布 - 订阅模式,让不同模块、组件之间可以解耦通信,且不依赖任何前端框架(Vue/React/ 原生 JS 均可使用)。
mitt 有什么特点?
- 极致轻量化:压缩后仅~200B,比
eventemitter3更小,适合嵌入任何项目;- 无依赖:纯原生 JS 实现,不绑定任何框架,跨平台兼容;
- API 极简:
on(订阅)、emit(发布)、off(取消订阅) 、all.clear(清除所有);- 支持 TypeScript:自带类型声明,类型提示友好;
- 支持通配符:可以用
*订阅所有事件,监听全局事件。
mitt
mitt-3.0.1/src/index.ts
function mitt<Events extends Record<EventType, unknown>>(
all?: EventHandlerMap<Events>
): Emitter<Events> {
type GenericEventHandler =
| Handler<Events[keyof Events]>
| WildcardHandler<Events>;
all = all || new Map();
return {
all,
// 注册事件处理器(订阅事件)。
// type:事件类型(如 'click'),必须是 Events 中定义的键或通配符 *。
// handler:事件触发时执行的函数。
on<Key extends keyof Events>(type: Key, handler: GenericEventHandler) {
// 从 all 映射表中获取该事件类型对应的处理器数组 handlers。
const handlers: Array<GenericEventHandler> | undefined = all!.get(type);
if (handlers) {
// 若存在,则将新处理器 push 到数组中;
handlers.push(handler);
} else {
// 若不存在,则初始化一个包含该处理器的数组并存入 all。
all!.set(type, [handler] as EventHandlerList<Events[keyof Events]>);
}
},
// 移除事件处理器(取消订阅)。
// type:事件类型。
// handler(可选):要移除的具体处理器;若不传,则移除该事件类型的所有处理器。
off<Key extends keyof Events>(type: Key, handler?: GenericEventHandler) {
// 从 all 中获取该事件的处理器数组 handlers。
const handlers: Array<GenericEventHandler> | undefined = all!.get(type);
if (handlers) {
if (handler) {
// 若指定了 handler:通过 indexOf 找到索引,用 splice 移除(>>> 0 确保索引为非负数,避免 indexOf 返回 -1 时的错误)。
handlers.splice(handlers.indexOf(handler) >>> 0, 1);
} else {
// 若未指定 handler:直接将该事件的处理器数组设为空数组(清空所有处理器)。
all!.set(type, []);
}
}
},
// 触发事件(发布事件),执行该事件的所有处理器。
// type:要触发的事件类型。
// evt(可选):事件参数,类型需匹配 Events[Key]。
emit<Key extends keyof Events>(type: Key, evt?: Events[Key]) {
let handlers = all!.get(type);
if (handlers) {
// 从 all 中获取该事件的处理器数组 handlers,通过 slice() 复制一份
// 遍历复制后的数组,依次执行每个处理器,并传入 evt 作为参数。
(handlers as EventHandlerList<Events[keyof Events]>)
.slice()
.map((handler) => {
handler(evt!);
});
}
// 从 all 中获取 '*' 对应的处理器数组,同样复制后遍历执行。
handlers = all!.get('*');
if (handlers) {
(handlers as WildCardEventHandlerList<Events>)
.slice()
.map((handler) => {
handler(type, evt!);
});
}
}
};
}
interface Emitter<Events extends Record<EventType, unknown>> {
all: EventHandlerMap<Events>;
on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void;
on(type: '*', handler: WildcardHandler<Events>): void;
off<Key extends keyof Events>(
type: Key,
handler?: Handler<Events[Key]>
): void;
off(type: '*', handler: WildcardHandler<Events>): void;
emit<Key extends keyof Events>(type: Key, event: Events[Key]): void;
emit<Key extends keyof Events>(
type: undefined extends Events[Key] ? Key : never
): void;
}