463 words
2 minutes
mitt 源码阅读
2025-02-24 15:26:50
2025-12-24 23:45:46
developit
/
mitt
Waiting for api.github.com...
00K
0K
0K
Waiting...
NOTE

mitt 是一个极简的事件发布订阅库,整个源码仅有 200 字节。它提供了事件的订阅、发布和取消订阅功能,是学习发布订阅模式的绝佳案例。

将类型删除转化为 js 代码,方便阅读:

export default function mitt(
	all = new Map();
): {
	return {
		all,
		on(type, handler) {
			const handlers= all!.get(type);
			if (handlers) {
				handlers.push(handler);
			} else {
				all!.set(type, [handler]);
			}
		},
		off(type, handler) {
			const handlers = all!.get(type);
			if (handlers) {
				if (handler) {
					handlers.splice(handlers.indexOf(handler) >>> 0, 1);
				} else {
					all!.set(type, []);
				}
			}
		},
		emit(type, evt) {
			let handlers = all!.get(type);
			if (handlers) {
				(handlers as EventHandlerList<Events[keyof Events]>)
					.slice()
					.map((handler) => {
						handler(evt!);
					});
			}

			handlers = all!.get('*');
			if (handlers) {
				(handlers as WildCardEventHandlerList<Events>)
					.slice()
					.map((handler) => {
						handler(type, evt!);
					});
			}
		}
	};
}
TIP

mitt 的核心是使用 Map 来存储事件和对应的处理函数列表。初始化时可以预设一些事件,以 {key: [...handlers]} 的形式存在。

核心功能解析#

1. 订阅事件 (on)#

on(type, handler)
NOTE
  • type: 事件类型
  • handler: 事件处理函数
  • 如果该事件类型已存在处理函数列表,则将新的处理函数追加到列表中
  • 如果是首次订阅该事件,则创建新的处理函数列表

2. 发布事件 (emit)#

emit(type, evt)
NOTE
  • type: 要触发的事件类型
  • evt: 传递给处理函数的事件数据
  • 会触发两类处理函数:
    1. 指定事件类型的处理函数列表
    2. 通配符 * 的处理函数列表(这些处理函数可以接收所有事件)

3. 取消订阅 (off)#

// 取消指定处理函数
off(type, handler)
// 取消该事件类型的所有处理函数
off(type)
NOTE
  • 可以选择性地移除单个处理函数,或清空某个事件类型的所有处理函数
  • 使用 handlers.splice(handlers.indexOf(handler) >>> 0, 1) 来安全地移除指定处理函数
  • >>> 0 操作确保了在找不到处理函数时(返回 -1)不会发生错误
mitt 源码阅读
https://0bipinnata0.my/posts/source-code-reading/mitt/
Author
0bipinnata0
Published at
2025-02-24 15:26:50