业务层组件自动绑定到实体属性上,优化开发体验

This commit is contained in:
dgflash
2026-02-22 18:37:27 +08:00
parent e206e43268
commit a226450564
3 changed files with 33 additions and 25 deletions

View File

@@ -269,7 +269,7 @@ export class ECSEntity {
remove(ctor: CompType<ecs.IComp>, isRecycle = true): void {
const componentTypeId = typeof ctor === 'number' ? ctor : ctor.tid;
const compName = typeof ctor === 'number' ? '' : ctor.compName;
if (!this.mask.has(componentTypeId)) {
return;
}
@@ -280,7 +280,7 @@ export class ECSEntity {
}
comp.ent = null!;
if (isRecycle) {
comp.reset();
@@ -296,7 +296,8 @@ export class ECSEntity {
// 限制缓存组件数量,防止内存泄漏
if (this.compTid2Obj.size < ECSEntity.MAX_CACHE_COMP) {
this.compTid2Obj.set(componentTypeId, comp); // 用于缓存显示对象组件
} else {
}
else {
// 超过限制,强制回收
console.warn(`实体 ${this.name} 缓存组件数量超过限制,强制回收组件 ${compName}`);
comp.reset();
@@ -338,10 +339,10 @@ export class ECSEntity {
// 移除实体上所有组件
this.compTid2Ctor.forEach(this._remove, this);
destroyEntity(this);
// 清理缓存的组件对象,防止内存泄漏
this.compTid2Obj.clear();
// 回收 mask 到对象池
this.mask.destroy();
}

View File

@@ -224,6 +224,10 @@ export abstract class CCEntity extends ecs.Entity {
//@ts-ignore
business.init();
this.businesss.set(cls, business);
// 将业务逻辑组件直接附加到实体对象身上,方便直接获取
Reflect.set(this, cls.name, business);
return business as T;
}
@@ -247,6 +251,9 @@ export abstract class CCEntity extends ecs.Entity {
if (business) {
business.destroy();
this.businesss.delete(cls);
// 清理实体上的业务逻辑组件引用
Reflect.set(this, cls.name, null);
}
}
}

View File

@@ -43,7 +43,7 @@ export class RoleViewComp extends CCView<Role> {
@ecs.register('LoadingView', false)
export class LoadingViewComp extends CCView<Initialize> {
protected mvvm = true; // 启用 MVVM 功能
data: LoadingData = {
finished: 0,
total: 0,
@@ -70,15 +70,15 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
//#region MVVM 功能相关(仅在 mvvm = true 时使用)
/** 是否启用 MVVM 功能(子类可覆盖为 true */
protected mvvm: boolean = false;
/**
protected mvvm = false;
/**
* MVVM 绑定的标签,延迟初始化以节省内存
* 仅在启用 MVVM 时创建
*/
protected tag?: string;
/**
/**
* 需要绑定的私有数据
* 注意:子类应该显式初始化此属性
*/
@@ -109,11 +109,11 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
// 优化:只在必要时替换点号,使用更快的 replaceAll如果支持
this.tag = `_temp<${uuid.replace('.', '')}>`;
VM.add(this.data!, this.tag);
// 搜寻所有节点:找到 watch path
const comps = this.getVMComponents();
const len = comps.length;
// 优化:避免属性查找,缓存 tag
const tag = this.tag;
for (let i = 0; i < len; i++) {
@@ -143,7 +143,7 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
// @ts-ignore - 优化:使用 any 类型避免多次类型转换
const vmComp: any = comp;
const path: string = vmComp.watchPath;
// 优化:使用严格相等避免类型转换
if (vmComp.templateMode === true) {
const pathArr: string[] = vmComp.watchPathArr;
@@ -171,20 +171,20 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
*/
private getVMComponents(): Component[] {
const comps = this.node.getComponentsInChildren(VMBase);
// 优化:提前返回,避免不必要的计算
if (comps.length === 0) {
return comps;
}
// 优化:只在有嵌套 CCView 时才获取 parents
const parents = this.node.getComponentsInChildren(CCView);
// 优化:使用数组长度判断,避免创建新数组
let hasNested = false;
const len = parents.length;
const myUuid = this.uuid;
for (let i = 0; i < len; i++) {
const p = parents[i];
if (p.uuid !== myUuid && p.mvvm) {
@@ -219,7 +219,7 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
result.push(comps[i]);
}
}
return result;
}
@@ -229,20 +229,20 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
console.error(`组件 ${this.name} 移除失败,实体不存在`);
return;
}
if (this.tid < 0) {
console.error(`组件 ${this.name} 移除失败,组件未注册 (tid=${this.tid})`);
return;
}
const cct = ECSModel.compCtors[this.tid];
if (!cct) {
console.error(`组件 ${this.name} 移除失败,组件构造函数不存在 (tid=${this.tid})`);
return;
}
this.ent.removeUi(cct);
this.ent = null!; // 清空引用,避免内存泄漏
this.ent = null!; // 清空引用,避免内存泄漏
}
/**
@@ -260,7 +260,7 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
// @ts-ignore - 优化:显式清空引用,帮助 GC
this.tag = undefined;
}
// @ts-ignore - 优化:显式清空引用,帮助 GC
this.data = undefined;
}
@@ -269,4 +269,4 @@ export abstract class CCView<T extends CCEntity> extends GameComponent implement
}
abstract reset(): void;
}
}