装饰器事件自动清理

This commit is contained in:
YHH
2025-09-28 23:58:43 +08:00
parent 05f04ef37e
commit b82891caee
3 changed files with 456 additions and 17 deletions

View File

@@ -469,39 +469,114 @@ export class GlobalEventBus {
/**
* 事件装饰器工厂
* 用于自动注册事件监听器
* 用于自动注册事件监听器,支持自动清理
*/
export function EventHandler(eventType: string, config: IEventListenerConfig = {}) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
// 存储装饰器信息
if (!target.constructor._eventHandlers) {
target.constructor._eventHandlers = [];
}
target.constructor._eventHandlers.push({
eventType,
methodName: propertyKey,
config
});
// 在类实例化时自动注册监听器
const initMethod = target.constructor.prototype.initEventListeners || function() {};
target.constructor.prototype.initEventListeners = function() {
initMethod.call(this);
// 初始化监听器追踪数组
if (!this._decoratorEventListeners) {
this._decoratorEventListeners = [];
}
const eventBus = GlobalEventBus.getInstance();
eventBus.on(eventType, originalMethod.bind(this), config);
const listenerId = eventBus.on(eventType, originalMethod.bind(this), config);
// 保存监听器ID用于后续清理
this._decoratorEventListeners.push({
eventType,
methodName: propertyKey,
listenerId
});
};
// 添加清理方法
const cleanupMethod = target.constructor.prototype.cleanupEventListeners || function() {};
target.constructor.prototype.cleanupEventListeners = function() {
cleanupMethod.call(this);
if (this._decoratorEventListeners) {
const eventBus = GlobalEventBus.getInstance();
for (const listener of this._decoratorEventListeners) {
eventBus.off(listener.eventType, listener.listenerId);
}
this._decoratorEventListeners.length = 0;
}
};
return descriptor;
};
}
/**
* 异步事件装饰器工厂
* 用于自动注册异步事件监听器
* 用于自动注册异步事件监听器,支持自动清理
*/
export function AsyncEventHandler(eventType: string, config: IEventListenerConfig = {}) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
// 存储装饰器信息
if (!target.constructor._eventHandlers) {
target.constructor._eventHandlers = [];
}
target.constructor._eventHandlers.push({
eventType,
methodName: propertyKey,
config,
async: true
});
const initMethod = target.constructor.prototype.initEventListeners || function() {};
target.constructor.prototype.initEventListeners = function() {
initMethod.call(this);
// 初始化监听器追踪数组
if (!this._decoratorEventListeners) {
this._decoratorEventListeners = [];
}
const eventBus = GlobalEventBus.getInstance();
eventBus.onAsync(eventType, originalMethod.bind(this), config);
const listenerId = eventBus.onAsync(eventType, originalMethod.bind(this), config);
// 保存监听器ID用于后续清理
this._decoratorEventListeners.push({
eventType,
methodName: propertyKey,
listenerId
});
};
// 添加清理方法
const cleanupMethod = target.constructor.prototype.cleanupEventListeners || function() {};
target.constructor.prototype.cleanupEventListeners = function() {
cleanupMethod.call(this);
if (this._decoratorEventListeners) {
const eventBus = GlobalEventBus.getInstance();
for (const listener of this._decoratorEventListeners) {
eventBus.off(listener.eventType, listener.listenerId);
}
this._decoratorEventListeners.length = 0;
}
};
return descriptor;
};
}

View File

@@ -18,6 +18,7 @@ interface EventListenerRecord {
listenerRef: string;
}
/**
* 实体系统的基类
*
@@ -52,6 +53,10 @@ export abstract class EntitySystem implements ISystemBase {
private _scene: Scene | null;
protected logger = createLogger('EntitySystem');
// 装饰器动态添加的方法(可选)
protected initEventListeners?: () => void;
protected cleanupEventListeners?: () => void;
/**
* 实体ID映射缓存
*/
@@ -134,6 +139,9 @@ export abstract class EntitySystem implements ISystemBase {
this._entityIdMapVersion = -1;
this._entityIdMapSize = 0;
// 初始化装饰器事件监听器
this.initDecoratorEventListeners();
this._entityCache = {
frame: null,
persistent: null,
@@ -238,10 +246,8 @@ export abstract class EntitySystem implements ISystemBase {
this._entityIdMapSize = 0;
// 清理所有事件监听器
this.cleanupEventListeners();
// 调用用户可重写的销毁方法
this.onDestroy();
// 调用框架销毁方法
this.destroy();
}
/**
@@ -746,12 +752,29 @@ export abstract class EntitySystem implements ISystemBase {
}
}
/**
* 清理所有事件监听器
*
* 系统移除时自动调用清理所有通过addEventListener添加的监听器。
* 初始化装饰器事件监听器
*/
private cleanupEventListeners(): void {
protected initDecoratorEventListeners(): void {
if (this.initEventListeners) {
this.initEventListeners();
}
}
/**
* 清理装饰器事件监听器
*/
protected cleanupDecoratorEventListeners(): void {
if (this.cleanupEventListeners) {
this.cleanupEventListeners();
}
}
/**
* 清理手动添加的事件监听器
*/
private cleanupManualEventListeners(): void {
for (const listener of this._eventListeners) {
try {
listener.eventSystem.off(listener.eventType, listener.listenerRef);
@@ -765,7 +788,22 @@ export abstract class EntitySystem implements ISystemBase {
}
/**
* 系统销毁时的回调
* 框架内部销毁方法
* 由框架调用,处理系统的完整销毁流程
*/
public destroy(): void {
// 1. 清理手动添加的事件监听器
this.cleanupManualEventListeners();
// 2. 清理装饰器事件监听器
this.cleanupDecoratorEventListeners();
// 3. 调用用户的销毁回调
this.onDestroy();
}
/**
* 用户销毁回调
*
* 当系统从场景中移除时调用,子类可以重写此方法进行清理操作。
* 注意:事件监听器会被框架自动清理,无需手动处理。