原理:设计模式-观察者模式与发布订阅模式_观察者模式事件名-CSDN博客
实际操作:
interface EventCallback {
context?: any;
callback: (...args: any[]) => any;
}
export interface Event {
on(eventName: string, callback: (...args: any[]) => any, context?: any, force?: boolean): Event;
off(eventName: string, callback?: (...args: any[]) => any): Event;
clear(): void;
emit(eventName: string, data: any): boolean;
}
// call is faster than apply, optimize less than 3 argu
// http://blog.csdn.net/zhengyinhui100/article/details/7837127
function emitEvents(events: EventCallback[], args: any[], context?: any): void {
if (args.length === 0) {
for (const event of events) {
event.callback.call(context || event.context);
}
return;
}
if (args.length <= 3) {
for (const event of events) {
event.callback.call(context || event.context, ...args);
}
return;
}
for (const event of events) {
event.callback.apply(context || event.context, args);
}
}
/**
* example:
* 订阅:
* ObserverEvent.on(EventName,this.userInfo,this);
* 发布:
* ObserverEvent.emit(EventName,{userName:"小明",age:18,sex:"man"});
* 取消订阅:
* ObserverEvent.on(EventName,this.userInfo);
*/
export default class ObserverEvent {
private static _eventMap: Map<string, EventCallback[]> = new Map<string, EventCallback[]>();
private static _eventOnceMap: Map<string, EventCallback[]> = new Map<string, EventCallback[]>();
/**
* 注册回调
* @param eventName 事件名
* @param callback 回调函数
* @param context 上下文
* @returns
*/
public static on(eventName: string, callback: (...args: any[]) => any, context?: any): Event {
if (!this._eventMap.has(eventName)) this._eventMap.set(eventName, []);
this._eventMap.get(eventName).push({
callback,
context,
});
return this;
}
/**
* 删除回调,如果有callback则删除事件中指定回调,否则删除事件名的所有回调
* @param eventName 事件名
* @param callback 回调函数
* @returns
*/
public static off(eventName: string, callback?: (...args: any[]) => void): Event {
if (!this._eventMap.has(eventName)) return this;
if (!callback) {
delete this._eventMap[eventName];
return;
}
const events = this._eventMap.get(eventName);
const index = events.findIndex((event) => event.callback === callback);
if (events[index]) {
events.splice(index, 1);
}
if (0 === events.length) delete this._eventMap[eventName];
return this;
}
/**
* 发布事件
* @param eventName 事件名
* @param args 参数
* @returns
*/
public static emit(eventName: string, ...args: any): boolean {
if (!this._eventMap.has(eventName)) return false;
const events = this._eventMap.get(eventName);
emitEvents(events, args);
return true;
}
/**
* 注册一次性事件
* @param eventName 事件名
* @param callback 回调函数
* @param context 上下文
* @returns
*/
public static onOnce(eventName: string, callback: (...args: any[]) => any, context?: any): Event {
if (!this._eventOnceMap.has(eventName)) this._eventOnceMap.set(eventName, []);
this._eventOnceMap.get(eventName).push({
callback,
context,
});
return this;
}
/**
* 发布一次性事件
* @param eventName
* @param args
* @returns
*/
public static emitOnce(eventName: string, ...args: any): boolean {
if (!this._eventOnceMap.has(eventName)) return false;
const events = this._eventOnceMap.get(eventName);
emitEvents(events, args);
this._eventOnceMap.delete(eventName);
return true;
}
/**
* 删除一次性事件,如果有callback则删除事件中指定回调,否则删除事件名的所有回调
* @param eventName
* @param callback
* @returns
*/
public static offOnce(eventName: string, callback?: (...args: any[]) => void): Event {
const eventMap = this._eventOnceMap;
if (!eventMap.has(eventName)) return this;
if (!callback) {
eventMap.delete(eventName);
return this;
}
const events = eventMap.get(eventName);
const index = events.findIndex((event) => event.callback === callback);
if (events[index]) {
events.splice(index, 1);
}
if (0 === events.length) delete this._eventMap[eventName];
return this;
}
public static clear(): void {
this._eventMap.clear();
this._eventOnceMap.clear();
}
}