// 从完整事件名称中提取原始事件名称(移除作用域前缀) type ExtractOriginalEventName = T extends `${S}:${infer Original}` ? Original : never // 从完整事件映射中提取原始事件映射 type ExtractBaseEventMaps, S extends string> = { [K in keyof T as ExtractOriginalEventName]: T[K] } type FireFN = (...argu: any[]) => void // 支持作用域的事件类 class ScopedFireEvent< T extends Record, // 完整的事件映射类型 S extends string, // 作用域类型 B extends Record = ExtractBaseEventMaps, // 从完整事件映射中提取的基础事件映射 > { #scope: S #events: Record = {} constructor(scope: S) { this.#scope = scope } // 获取完整的事件名称(添加作用域前缀) public getFullEventName(eventName: string): string { if (this.#scope === "") return eventName return `${this.#scope}:${eventName}` } print() { Object.keys(this.#events).forEach(key => { console.log(`${key}: ${this.#events[key]}\n`) }) } // 订阅事件,支持自动添加作用域前缀 on(name: K, fn: B[K]) { const fullName = this.getFullEventName(name as string) if (!this.#events[fullName]) { this.#events[fullName] = [] } this.#events[fullName].push(fn as FireFN) } // 触发事件,支持自动添加作用域前缀 emit(name: K, ...argu: Parameters) { const fullName = this.getFullEventName(name as string) if (this.#events[fullName]) { this.#events[fullName].forEach(fn => { fn(...argu) }) } } // 取消订阅事件,支持自动添加作用域前缀 off(name: K, fn?: B[K]) { const fullName = this.getFullEventName(name as string) const len = this.#events[fullName]?.length || 0 if (!len) { return } if (!fn) { this.#events[fullName] = [] } else { for (let i = len - 1; i >= 0; i--) { const _fn = this.#events[fullName][i] if (_fn === fn) { this.#events[fullName].splice(i, 1) } } } } // 一次性订阅事件,支持自动添加作用域前缀 once(name: K, fn: B[K]) { const _fn: FireFN = (...argu: any[]) => { fn(...argu) this.off(name, _fn as B[K]) } this.on(name, _fn as B[K]) } } // 创建作用域事件发射器的工厂函数 - 仅需一个泛型参数 export function buildEmitter>(scope?: string): ScopedFireEvent { return new ScopedFireEvent(scope) }