100 lines
2.8 KiB
TypeScript
100 lines
2.8 KiB
TypeScript
type EventCallback = (data?: any) => void
|
|
|
|
class CallbackAndContext {
|
|
public callback: EventCallback = null
|
|
public context: any = null
|
|
|
|
public constructor(callback: EventCallback, context: any) {
|
|
this.callback = callback
|
|
this.context = context
|
|
}
|
|
}
|
|
|
|
export class EventManager {
|
|
private static instance: EventManager = null
|
|
private listeners: { [eventName: string]: Array<CallbackAndContext> }
|
|
|
|
public static Instance(): EventManager {
|
|
if (!this.instance) {
|
|
this.instance = new EventManager()
|
|
}
|
|
return this.instance
|
|
}
|
|
|
|
public On(eventName: string, callback: EventCallback, context?: any): void {
|
|
if (!this.listeners[eventName]) {
|
|
this.listeners[eventName] = []
|
|
}
|
|
if (!callback) return
|
|
if (this.IsExsit(eventName, callback, context)) return
|
|
this.listeners[eventName].push(new CallbackAndContext(callback, context))
|
|
}
|
|
|
|
private IsExsit(eventName: string, callback: EventCallback, context?: any): boolean {
|
|
const listeners = this.listeners[eventName]
|
|
if (!listeners) return false
|
|
|
|
for (let i = listeners.length - 1; i >= 0; i--) {
|
|
const listener = listeners[i]
|
|
if (listener.callback === callback && (!context || listener.context === context)) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// 取消事件监听
|
|
public Off(eventName: string, callback?: EventCallback, context?: any): void {
|
|
const listeners = this.listeners[eventName]
|
|
if (!listeners) return
|
|
// 如果没有提供回调,则移除该事件的所有监听
|
|
if (!callback) {
|
|
delete this.listeners[eventName]
|
|
return
|
|
}
|
|
for (let i = listeners.length - 1; i >= 0; i--) {
|
|
const listener = listeners[i]
|
|
if (listener.callback === callback && (!context || listener.context === context)) {
|
|
listeners.splice(i, 1)
|
|
}
|
|
}
|
|
if (listeners.length === 0) {
|
|
delete this.listeners[eventName]
|
|
}
|
|
}
|
|
|
|
// 触发事件
|
|
public Emit(eventName: string, data?: any): void {
|
|
const listener = this.listeners[eventName]
|
|
if (!listener) return
|
|
// 创建副本,防止回调中修改原始数组
|
|
const copy = [...listener]
|
|
copy.forEach((listener) => {
|
|
try {
|
|
listener.callback.call(listener.context, data)
|
|
} catch (error) {
|
|
console.error(`事件回调错误,事件名: ${eventName}:`, error)
|
|
}
|
|
})
|
|
}
|
|
|
|
// 一次性监听(触发后自动移除)
|
|
public Once(eventName: string, callback: EventCallback, context?: any): void {
|
|
const wrapper = (data: any) => {
|
|
callback.call(context, data)
|
|
this.Off(eventName, wrapper, context)
|
|
}
|
|
this.On(eventName, wrapper, context)
|
|
}
|
|
|
|
// 移除所有事件监听
|
|
public ClearAll(): void {
|
|
this.listeners = {}
|
|
}
|
|
|
|
// 获取某个事件的监听者数量
|
|
public ListenerCount(eventName: string): number {
|
|
return this.listeners[eventName]?.length || 0
|
|
}
|
|
}
|