优化Framework.UI新增便捷接口
This commit is contained in:
1926
client/.github/instructions/development-plan.md
vendored
1926
client/.github/instructions/development-plan.md
vendored
File diff suppressed because it is too large
Load Diff
@@ -123,9 +123,16 @@ export class UILogin extends UIBase {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 必须重载: 返回 UI 资源路径
|
* 必须重载: 返回 UI 资源路径
|
||||||
|
*
|
||||||
|
* 编写规则:
|
||||||
|
* 1. 普通资源路径: 'prefabs/ui/UILogin'
|
||||||
|
* 2. Bundle资源路径: '[bundle名]://资源路径'
|
||||||
|
* 示例: 'ui-bundle://prefabs/UILogin'
|
||||||
*/
|
*/
|
||||||
onGetUrl(): string {
|
onGetUrl(): string {
|
||||||
return 'prefabs/ui/UILogin';
|
return 'prefabs/ui/UILogin';
|
||||||
|
// 或使用 bundle 方式:
|
||||||
|
// return 'ui-bundle://prefabs/UILogin';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -323,6 +330,8 @@ onEnd() - 清理资源(可选)
|
|||||||
## ⚠️ 注意事项
|
## ⚠️ 注意事项
|
||||||
|
|
||||||
1. **必须重载 onGetUrl()**: 每个 UI 必须明确定义资源路径
|
1. **必须重载 onGetUrl()**: 每个 UI 必须明确定义资源路径
|
||||||
|
- 普通资源路径格式: `'prefabs/ui/UILogin'`
|
||||||
|
- Bundle资源路径格式: `'[bundle名]://资源路径'` (例如: `'ui-bundle://prefabs/UILogin'`)
|
||||||
2. **UI 根节点设置**: 在加载任何 UI 之前,必须先设置 UI 根节点
|
2. **UI 根节点设置**: 在加载任何 UI 之前,必须先设置 UI 根节点
|
||||||
3. **缓存机制**: 已加载的 UI 会被缓存,再次加载时直接使用缓存
|
3. **缓存机制**: 已加载的 UI 会被缓存,再次加载时直接使用缓存
|
||||||
4. **资源自动管理**: UIMgr 会自动管理资源加载和释放
|
4. **资源自动管理**: UIMgr 会自动管理资源加载和释放
|
||||||
@@ -367,7 +376,11 @@ if (canvas) {
|
|||||||
```typescript
|
```typescript
|
||||||
// 检查: 资源路径是否正确
|
// 检查: 资源路径是否正确
|
||||||
onGetUrl(): string {
|
onGetUrl(): string {
|
||||||
return 'prefabs/ui/UILogin'; // 确保路径正确
|
// 普通资源路径
|
||||||
|
return 'prefabs/ui/UILogin';
|
||||||
|
|
||||||
|
// 或使用 Bundle 资源路径
|
||||||
|
// return 'ui-bundle://prefabs/UILogin';
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -383,6 +396,8 @@ if (!UIMgr.getInstance().has(UILogin)) {
|
|||||||
|
|
||||||
1. **单一职责**: 每个 UI 类只负责一个界面
|
1. **单一职责**: 每个 UI 类只负责一个界面
|
||||||
2. **资源路径统一**: 建议在配置文件中统一管理 UI 资源路径
|
2. **资源路径统一**: 建议在配置文件中统一管理 UI 资源路径
|
||||||
|
- 对于需要分包加载的 UI,使用 Bundle 路径格式: `'[bundle名]://资源路径'`
|
||||||
|
- 对于通用 UI,使用普通路径格式: `'资源路径'`
|
||||||
3. **事件解绑**: 在 onEnd() 中解绑所有事件,避免内存泄漏
|
3. **事件解绑**: 在 onEnd() 中解绑所有事件,避免内存泄漏
|
||||||
4. **参数传递**: 使用 params 参数在加载时传递初始数据
|
4. **参数传递**: 使用 params 参数在加载时传递初始数据
|
||||||
5. **缓存利用**: 对频繁切换的 UI,利用缓存避免重复加载
|
5. **缓存利用**: 对频繁切换的 UI,利用缓存避免重复加载
|
||||||
|
|||||||
11
client/assets/scripts/Framework/UI/README.md.meta
Normal file
11
client/assets/scripts/Framework/UI/README.md.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.1",
|
||||||
|
"importer": "text",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "fbfe85a1-0fe1-4ac7-b004-36c370c6a4eb",
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Node } from 'cc';
|
import { Node, Component, Button } from 'cc';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UI基类
|
* UI基类
|
||||||
@@ -121,4 +121,67 @@ export abstract class UIBase {
|
|||||||
isLoaded(): boolean {
|
isLoaded(): boolean {
|
||||||
return this._isLoaded;
|
return this._isLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找子节点并获取组件
|
||||||
|
* @param path 节点路径,支持多层级查找(如: 'mid/input_account')
|
||||||
|
* @param componentType 组件类型
|
||||||
|
* @returns 组件实例,未找到则返回null
|
||||||
|
* @example
|
||||||
|
* const editBox = this.GetChild('mid/input_account', EditBox);
|
||||||
|
* const button = this.GetChild('btn_login', Button);
|
||||||
|
*/
|
||||||
|
protected GetChild<T extends Component>(path: string, componentType: { new(): T }): T | null {
|
||||||
|
if (!this._node) {
|
||||||
|
console.error('[UIBase] GetChild失败: UI根节点不存在');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const childNode = this._node.getChildByPath(path);
|
||||||
|
if (!childNode) {
|
||||||
|
console.error(`[UIBase] GetChild失败: 未找到节点 ${path}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const component = childNode.getComponent(componentType);
|
||||||
|
if (!component) {
|
||||||
|
console.error(`[UIBase] GetChild失败: 节点 ${path} 未挂载 ${componentType.name} 组件`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置按钮点击事件
|
||||||
|
* @param button Button组件或包含Button组件的Node
|
||||||
|
* @param callback 点击回调函数
|
||||||
|
* @param target 回调函数的this指向
|
||||||
|
* @example
|
||||||
|
* const btn = this.GetChild('btn_login', Button);
|
||||||
|
* this.SetClick(btn, this.onLoginClick, this);
|
||||||
|
*/
|
||||||
|
protected SetClick(button: Button | Node | null, callback: () => void, target?: any): void {
|
||||||
|
if (!button) {
|
||||||
|
console.error('[UIBase] SetClick失败: button为null');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let targetNode: Node | null = null;
|
||||||
|
|
||||||
|
// 判断是Button组件还是Node
|
||||||
|
if (button instanceof Button) {
|
||||||
|
targetNode = button.node;
|
||||||
|
} else if (button instanceof Node) {
|
||||||
|
targetNode = button;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!targetNode) {
|
||||||
|
console.error('[UIBase] SetClick失败: 无法获取目标节点');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绑定点击事件
|
||||||
|
targetNode.on(Node.EventType.TOUCH_END, callback, target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,12 +82,14 @@ export class UIMgr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[UIMgr] 开始加载UI: ${className} (${url})`);
|
console.log(`[UIMgr] 开始加载UI: ${className} (${url})`);
|
||||||
|
const args = url.split('://')
|
||||||
|
const bundleName = args[0];
|
||||||
|
const resourcePath = args[1];
|
||||||
// 通过ResMgr加载预制体
|
// 通过ResMgr加载预制体
|
||||||
try {
|
try {
|
||||||
const prefab = await ResMgr.getInstance().load<Prefab>(
|
const prefab = await ResMgr.getInstance().load<Prefab>(
|
||||||
'resources',
|
bundleName,
|
||||||
url,
|
resourcePath,
|
||||||
Prefab
|
Prefab
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user