Skip to content
On this page

Emitter

发布订阅设计模式

mitt - 200 byte

类型定义

mitt ts 类型声明

ts
// 事件类型
export type EventType = string | symbol;

// 事件类型的事件处理函数类型
export type Handler<T = unknown> = (event: T) => void;
export type WildcardHandler<T = Record<string, unknown>> = (
	type: keyof T,
	event: T[keyof T]
) => void;

// 当前事件类型对应的事件处理函数列表类型
export type EventHandlerList<T = unknown> = Array<Handler<T>>;
export type WildCardEventHandlerList<T = Record<string, unknown>> = Array<WildcardHandler<T>>;

// 事件类型及其对应事件处理函数列表的映射
export type EventHandlerMap<Events extends Record<EventType, unknown>> = Map<
	keyof Events | '*',
	EventHandlerList<Events[keyof Events]> | WildCardEventHandlerList<Events>
>;

// mitt 函数返回的类型
export 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;
}

mitt

整个库导出一个 mitt 函数,可选参数 all 是一个 Map 数据类型。返回一个 Emitter 类型。

ts
export default 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,
    // 监听对应事件类型的事件处理函数
    on<Key extends keyof Events>(type: Key, handler: GenericEventHandler){},
    // 关闭对应事件类型的事件处理函数
    off<Key extends keyof Events>(type: Key, handler?: GenericEventHandler){},
    // 触发对应事件类型的事件处理函数
    emit<Key extends keyof Events>(type: Key, evt?: Events[Key]){},
  }
}

on

为给定类型注册事件处理程序。

ts
on<Key extends keyof Events>(type: Key, handler: GenericEventHandler) {
  // 获取给定类型的事件处理程序列表
  const handlers: Array<GenericEventHandler> | undefined = all!.get(type);
  if (handlers) {
    // 有,直接往后在添加事件处理程序
    handlers.push(handler);
  }
  else {
    // 无,则新添加事件处理程序列表
    all!.set(type, [handler] as EventHandlerList<Events[keyof Events]>);
  }
},

off

删除给定类型的事件处理程序。

ts
off<Key extends keyof Events>(type: Key, handler?: GenericEventHandler) {
  // 获取给定类型的事件处理程序列表
  const handlers: Array<GenericEventHandler> | undefined = all!.get(type);
  if (handlers) {
    // 有,则判断列表中是否有对应具体的事件处理程序函数。
    if (handler) {
      // 有具体的事件处理程序函数,则从列表中删除具体的处理函数。
      handlers.splice(handlers.indexOf(handler) >>> 0, 1);
    }
    else {
      // 无,则将给定类型所有的事件处理程序置为空数组。
      all!.set(type, []);
    }
  }
},

emit

调用给定类型的所有处理程序。

TIP

在遍历执行所有的事件处理程序的时候,有做一个 slice 浅拷贝的操作。为了处理这个 issues 所带来的问题。

ts
emit<Key extends keyof Events>(type: Key, evt?: Events[Key]) {
  // 获取给定类型的事件处理程序列表
  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!);
      });
  }
}