Files
kevisual-home/packages/kv-login/src/modules/mitt.ts
2025-12-01 02:19:44 +08:00

134 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export interface EventData<T = any> {
type: string;
data: T;
}
export type EventHandler<T = any> = (event: EventData<T>) => void;
export class EventEmitter {
private events: Map<string, Set<EventHandler>> = new Map();
/**
* 监听事件
* @param type 事件类型
* @param handler 事件处理函数
*/
on<T = any>(type: string, handler: EventHandler<T>): void {
if (!this.events.has(type)) {
this.events.set(type, new Set());
}
this.events.get(type)!.add(handler);
}
/**
* 移除事件监听器
* @param type 事件类型
* @param handler 事件处理函数 (可选,如果不提供则移除该类型的所有监听器)
*/
off<T = any>(type: string, handler?: EventHandler<T>): void {
if (!this.events.has(type)) {
return;
}
if (handler) {
this.events.get(type)!.delete(handler);
// 如果该类型没有监听器了,删除该类型
if (this.events.get(type)!.size === 0) {
this.events.delete(type);
}
} else {
// 移除该类型的所有监听器
this.events.delete(type);
}
}
/**
* 触发事件
* @param event 事件对象,包含 type 和 data
*/
emit<T = any>(event: EventData<T>): void {
const { type } = event;
if (!this.events.has(type)) {
return;
}
const handlers = this.events.get(type)!;
handlers.forEach(handler => {
try {
handler(event);
} catch (error) {
console.error(`Error in event handler for type "${type}":`, error);
}
});
}
/**
* 触发事件简化版本直接传递type和data
* @param type 事件类型
* @param data 事件数据
*/
emitSimple<T = any>(type: string, data: T): void {
this.emit({ type, data });
}
/**
* 清空所有事件监听器
*/
clear(): void {
this.events.clear();
}
/**
* 获取指定类型的监听器数量
* @param type 事件类型
* @returns 监听器数量
*/
listenerCount(type: string): number {
return this.events.get(type)?.size || 0;
}
/**
* 获取所有事件类型
* @returns 事件类型数组
*/
eventNames(): string[] {
return Array.from(this.events.keys());
}
/**
* 检查是否有指定类型的监听器
* @param type 事件类型
* @returns 是否有监听器
*/
hasListeners(type: string): boolean {
return this.events.has(type) && this.events.get(type)!.size > 0;
}
/**
* 只监听一次事件
* @param type 事件类型
* @param handler 事件处理函数
*/
once<T = any>(type: string, handler: EventHandler<T>): void {
const onceHandler: EventHandler<T> = (event) => {
handler(event);
this.off(type, onceHandler);
};
this.on(type, onceHandler);
}
}
// 创建默认的事件发射器实例
export const eventEmitter = new EventEmitter();
// 导出便捷方法
export const on = <T = any>(type: string, handler: EventHandler<T>) => eventEmitter.on(type, handler);
export const off = <T = any>(type: string, handler?: EventHandler<T>) => eventEmitter.off(type, handler);
export const emit = <T = any>(event: EventData<T>) => eventEmitter.emit(event);
export const emitSimple = <T = any>(type: string, data: T) => eventEmitter.emitSimple(type, data);
export const clear = () => eventEmitter.clear();
export const once = <T = any>(type: string, handler: EventHandler<T>) => eventEmitter.once(type, handler);
// 默认导出
export default eventEmitter;