From 69547bcd6b421851c3746a5230d3da097a71d50f Mon Sep 17 00:00:00 2001 From: xingyu Date: Sun, 14 May 2023 17:20:39 +0800 Subject: [PATCH] feat: sync mitt --- src/utils/mitt.ts | 86 ++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/src/utils/mitt.ts b/src/utils/mitt.ts index 421af46..bf29561 100644 --- a/src/utils/mitt.ts +++ b/src/utils/mitt.ts @@ -2,32 +2,34 @@ * copy to https://github.com/developit/mitt * Expand clear method */ - export type EventType = string | symbol // An event handler can take an optional event argument // and should not return a value -export type Handler = (event?: T) => void -export type WildcardHandler = (type: EventType, event?: any) => void +export type Handler = (event: T) => void +export type WildcardHandler> = (type: keyof T, event: T[keyof T]) => void // An array of all currently registered event handlers for a type -export type EventHandlerList = Array -export type WildCardEventHandlerList = Array +export type EventHandlerList = Array> +export type WildCardEventHandlerList> = Array> // A map of event types and their corresponding event handlers. -export type EventHandlerMap = Map +export type EventHandlerMap> = Map< + keyof Events | '*', + EventHandlerList | WildCardEventHandlerList +> -export interface Emitter { - all: EventHandlerMap +export interface Emitter> { + all: EventHandlerMap - on(type: EventType, handler: Handler): void - on(type: '*', handler: WildcardHandler): void + on(type: Key, handler: Handler): void + on(type: '*', handler: WildcardHandler): void - off(type: EventType, handler: Handler): void - off(type: '*', handler: WildcardHandler): void + off(type: Key, handler?: Handler): void + off(type: '*', handler: WildcardHandler): void - emit(type: EventType, event?: T): void - emit(type: '*', event?: any): void + emit(type: Key, event: Events[Key]): void + emit(type: undefined extends Events[Key] ? Key : never): void clear(): void } @@ -36,7 +38,8 @@ export interface Emitter { * @name mitt * @returns {Mitt} */ -export default function mitt(all?: EventHandlerMap): Emitter { +export function mitt>(all?: EventHandlerMap): Emitter { + type GenericEventHandler = Handler | WildcardHandler all = all || new Map() return { @@ -47,48 +50,61 @@ export default function mitt(all?: EventHandlerMap): Emitter { /** * Register an event handler for the given type. - * @param {string|symbol} type Type of event to listen for, or `"*"` for all events + * @param {string|symbol} type Type of event to listen for, or `'*'` for all events * @param {Function} handler Function to call in response to given event * @memberOf mitt */ - on(type: EventType, handler: Handler) { - const handlers = all?.get(type) - const added = handlers && handlers.push(handler) - if (!added) { - all?.set(type, [handler]) + on(type: Key, handler: GenericEventHandler) { + const handlers: Array | undefined = all!.get(type) + if (handlers) { + handlers.push(handler) + } else { + all!.set(type, [handler] as EventHandlerList) } }, /** * Remove an event handler for the given type. - * @param {string|symbol} type Type of event to unregister `handler` from, or `"*"` - * @param {Function} handler Handler function to remove + * If `handler` is omitted, all handlers of the given type are removed. + * @param {string|symbol} type Type of event to unregister `handler` from (`'*'` to remove a wildcard handler) + * @param {Function} [handler] Handler function to remove * @memberOf mitt */ - off(type: EventType, handler: Handler) { - const handlers = all?.get(type) + off(type: Key, handler?: GenericEventHandler) { + const handlers: Array | undefined = all!.get(type) if (handlers) { - handlers.splice(handlers.indexOf(handler) >>> 0, 1) + if (handler) { + handlers.splice(handlers.indexOf(handler) >>> 0, 1) + } else { + all!.set(type, []) + } } }, /** * Invoke all handlers for the given type. - * If present, `"*"` handlers are invoked after type-matched handlers. + * If present, `'*'` handlers are invoked after type-matched handlers. * - * Note: Manually firing "*" handlers is not supported. + * Note: Manually firing '*' handlers is not supported. * * @param {string|symbol} type The event type to invoke * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler * @memberOf mitt */ - emit(type: EventType, evt: T) { - ;((all?.get(type) || []) as EventHandlerList).slice().map((handler) => { - handler(evt) - }) - ;((all?.get('*') || []) as WildCardEventHandlerList).slice().map((handler) => { - handler(type, evt) - }) + emit(type: Key, evt?: Events[Key]) { + let handlers = all!.get(type) + if (handlers) { + ;(handlers as EventHandlerList).slice().forEach((handler) => { + handler(evt as Events[Key]) + }) + } + + handlers = all!.get('*') + if (handlers) { + ;(handlers as WildCardEventHandlerList).slice().forEach((handler) => { + handler(type, evt as Events[Key]) + }) + } }, /**