2022-08-26 16:48:17 +08:00

126 lines
3.3 KiB
TypeScript

/**
* 回呼函數: fnname (arg: TArg): void
*/
interface ActionCallback<TArg> {
(arg: TArg): void;
}
interface Struct<TArg> {
callback: ActionCallback<TArg>;
target: any;
once?: boolean;
}
export class Action<TArg> {
private _queue: Struct<TArg>[] = [];
/**
* 監聽事件
* @param callback 回呼函數: fnname (arg: TArg): void
* @param bindTarget 回呼時this綁定的對象
*/
AddCallback(callback: ActionCallback<TArg>, bindTarget?: any) {
let q = <Struct<TArg>> {
callback: callback,
target: bindTarget
};
this._queue.push(q);
}
/**
* 監聽事件 (一次性)
* @param callback 回呼函數: fnname (arg: TArg): void
* @param bindTarget 回呼時this綁定的對象
*/
AddCallbackOnce(callback: ActionCallback<TArg>, bindTarget?: any) {
let q = <Struct<TArg>> {
callback: callback,
target: bindTarget,
once: true
};
this._queue.push(q);
}
/**
* 移除事件
* @param callback
*/
RemoveByCallback(callback: ActionCallback<TArg>) {
let index = this._queue.length;
if (index > 0) {
while (index--) {
let q = this._queue[index];
if (!q.callback || q.callback === callback) {
q.callback = undefined;
this._queue.splice(index, 1);
}
}
}
}
/**
* 移除事件
* @param bindTarget 回呼時this綁定的對象
*/
RemoveByBindTarget(bindTarget: any) {
let index = this._queue.length;
if (index > 0) {
while (index--) {
let q = this._queue[index];
if (!q.callback || q.target === bindTarget) {
q.callback = undefined;
this._queue.splice(index, 1);
}
}
}
}
/**
* 移除全部事件
*/
RemoveAllCallbacks() {
this._queue.forEach(q => q.callback = undefined);
this._queue.length = 0;
}
/**
* 發送事件
* @param arg 參數
*/
DispatchCallback(arg: TArg) {
let index = this._queue.length;
if (index > 0) {
let cleanRemoved = false;
this._queue.slice().forEach(q => {
if (!q.callback) {
cleanRemoved = true;
return;
}
if (q.target) {
q.callback.call(q.target, arg);
} else {
q.callback(arg);
}
if (q.once) {
q.callback = undefined;
cleanRemoved = true;
}
});
if (cleanRemoved) {
index = this._queue.length;
if (index > 0) {
while (index--) {
let q = this._queue[index];
if (!q.callback) {
this._queue.splice(index, 1);
}
}
}
}
}
}
}