mirror of
https://gitee.com/dgflash/oops-plugin-framework.git
synced 2026-05-22 08:36:41 +08:00
2. 存储模块性能提升,添加LRU缓存、批量操作支持,优化内存使用 3. 多语言模块性能与内存管理优化,组件查询性能提升 4. 时间模块类型安全与性能优化,使用泛型替代any,对象池机制减少内存分配 5. 事件系统修复双重注册、重复注册等严重问题,实现EventData对象池减少GC压力 6. RandomManager修复4个逻辑BUG,包括边界问题和越界问题 7. 音频模块内存与性能优化,避免重复加载,优化数据结构,添加完整清理机制 8. CCView与CCViewVM合并,支持按需启用MVVM 9. Collection模块优化,AsyncQueue添加队列容量限制,Collection查询性能提升 10. ECS系统全面优化,对象池复用减少内存分配,循环性能提升 11. 优化MVVM组件性能
126 lines
3.9 KiB
TypeScript
126 lines
3.9 KiB
TypeScript
import type { Component } from 'cc';
|
||
import { _decorator } from 'cc';
|
||
import { GameComponent } from '../../module/common/GameComponent';
|
||
import { VM } from './ViewModel';
|
||
import { VMBase } from './VMBase';
|
||
|
||
const { ccclass, help, executionOrder } = _decorator;
|
||
|
||
/**
|
||
* 提供VM环境,控制旗下所有VM节点
|
||
* 一般用于 非全局的 VM绑定,VM 环境与组件紧密相连
|
||
* (Prefab 模式绑定)
|
||
* VMParent 必须必其他组件优先执行
|
||
* 现在可以支持 Parent 嵌套(但是注意性能问题,不要频繁嵌套)
|
||
*/
|
||
@ccclass
|
||
@executionOrder(-1)
|
||
@help('https://gitee.com/dgflash/oops-framework/wikis/pages?sort_id=12037729&doc_id=2873565')
|
||
export default class VMParent extends GameComponent {
|
||
/** 绑定的标签,可以通过这个tag 获取 当前的 vm 实例 */
|
||
protected tag = '_temp';
|
||
|
||
/** 需要绑定的私有数据 */
|
||
protected data: any = {};
|
||
|
||
/**
|
||
* [注意]不能直接覆盖此方法,如果需要覆盖。
|
||
* 只能在该方法内部调用父类的实现
|
||
* ```ts
|
||
* onLoad(){
|
||
* super.onLoad();
|
||
* }
|
||
* ```
|
||
*/
|
||
onLoad() {
|
||
if (this.data == null) return;
|
||
this.onBind();
|
||
|
||
this.tag = '_temp' + '<' + this.node.uuid.replace('.', '') + '>';
|
||
VM.add(this.data, this.tag);
|
||
// log(VM['_mvs'],this.tag)
|
||
//搜寻所有节点:找到 watch path
|
||
const comps = this.getVMComponents();
|
||
// console.group();
|
||
for (let i = 0; i < comps.length; i++) {
|
||
const comp = comps[i];
|
||
this.replaceVMPath(comp, this.tag);
|
||
}
|
||
// console.groupEnd()
|
||
}
|
||
|
||
/**在 onLoad 完成 和 start() 之前调用,你可以在这里进行初始化数据等操作 */
|
||
protected onBind() { }
|
||
|
||
/**在 onDestroy() 后调用,此时仍然可以获取绑定的 data 数据*/
|
||
protected onUnBind() { }
|
||
|
||
private replaceVMPath(comp: Component, tag: string) {
|
||
// @ts-ignore
|
||
const path: string = comp['watchPath'];
|
||
// @ts-ignore
|
||
if (comp['templateMode'] == true) {
|
||
// @ts-ignore
|
||
const pathArr: string[] = comp['watchPathArr'];
|
||
if (pathArr) {
|
||
for (let i = 0; i < pathArr.length; i++) {
|
||
const path = pathArr[i];
|
||
pathArr[i] = path.replace('*', tag);
|
||
}
|
||
}
|
||
|
||
}
|
||
else {
|
||
// VMLabel
|
||
// 遇到特殊 path 就优先替换路径
|
||
if (path.split('.')[0] === '*') {
|
||
// @ts-ignore
|
||
comp['watchPath'] = path.replace('*', tag);
|
||
}
|
||
}
|
||
}
|
||
|
||
/** 优化的遍历节点,获取VM 组件 */
|
||
private getVMComponents() {
|
||
const comps = this.node.getComponentsInChildren(VMBase);
|
||
const parents = this.node.getComponentsInChildren(VMParent).filter((v) => v.uuid !== this.uuid); // 过滤掉自己
|
||
|
||
// 如果没有嵌套的 VMParent,直接返回所有组件
|
||
if (parents.length === 0) {
|
||
return comps;
|
||
}
|
||
|
||
// 使用 Set 优化过滤性能,避免 O(n²) 复杂度
|
||
const filterSet = new Set<Component>();
|
||
parents.forEach((parent: Component) => {
|
||
const childComps = parent.getComponentsInChildren(VMBase);
|
||
childComps.forEach(comp => filterSet.add(comp));
|
||
});
|
||
|
||
// 使用 Set.has() 代替 indexOf,性能更好
|
||
return comps.filter((v) => !filterSet.has(v));
|
||
}
|
||
|
||
/**
|
||
* [注意]不能覆盖此方法,如果需要覆盖。
|
||
* 需要在该方法内部调用父类的实现,再定义自己的方法
|
||
* ```ts
|
||
* onDestroy(){
|
||
* super.onDestroy();
|
||
* }
|
||
* ```
|
||
*/
|
||
protected onDestroy() {
|
||
this.onUnBind();
|
||
|
||
// 解除全部引用
|
||
VM.remove(this.tag);
|
||
// @ts-ignore
|
||
this.data = null;
|
||
// @ts-ignore
|
||
this.tag = null;
|
||
|
||
super.onDestroy();
|
||
}
|
||
}
|