Files
pixelheros/.qoder/repowiki/zh/content/技术架构/MVVM框架.md
panw 4235e3b776 refactor(game): 移除已弃用的事件常量
- 删除 UpdateHero 和 UpdateFightHero 事件
- 移除 MISSION_UPDATE 事件常量
- 优化游戏事件枚举定义
2025-10-28 16:15:47 +08:00

245 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MVVM框架
<cite>
**本文档引用的文件**
- [MvvmInfo.md](file://doc/mvvm/MvvmInfo.md)
- [VMBase.md](file://doc/mvvm/VMBase.md)
- [VMCustom.md](file://doc/mvvm/VMCustom.md)
- [VMLabel.md](file://doc/mvvm/VMLabel.md)
- [VMState.md](file://doc/mvvm/VMState.md)
- [VMProgress.md](file://doc/mvvm/VMProgress.md)
- [VMEvent.md](file://doc/mvvm/VMEvent.md)
- [VMParent.md](file://doc/mvvm/VMParent.md)
- [ViewModelScript.md](file://doc/mvvm/ViewModelScript.md)
- [GameUIConfig.ts](file://assets/script/game/common/config/GameUIConfig.ts)
- [HInfoComp.ts](file://assets/script/game/map/HInfoComp.ts)
- [SIconComp.ts](file://assets/script/game/map/SIconComp.ts)
</cite>
## 目录
1. [简介](#简介)
2. [核心组件](#核心组件)
3. [数据模型注册与管理](#数据模型注册与管理)
4. [UI组件与数据绑定机制](#ui组件与数据绑定机制)
5. [UI自动更新机制](#ui自动更新机制)
6. [编辑器配置与使用示例](#编辑器配置与使用示例)
7. [高级功能与最佳实践](#高级功能与最佳实践)
## 简介
Oops Plugin Framework的MVVM实现机制旨在通过数据驱动的方式简化UI逻辑开发实现无代码或低代码的UI开发模式。该框架借鉴了Vue的设计理念通过观察者模式和事件系统实现了数据与UI的双向绑定。开发者无需频繁使用`cc.find``getChildByName``getComponent`等繁琐的DOM操作而是通过简单的配置即可实现复杂的UI逻辑。
该框架的核心优势在于其组件化的实现方式提供了多个低耦合的VM组件如VMLabel、VMState、VMProgress等这些组件可以直接在Cocos Creator编辑器中挂载和配置极大地提高了开发效率和可维护性。
**Section sources**
- [MvvmInfo.md](file://doc/mvvm/MvvmInfo.md#L1-L51)
## 核心组件
### ViewModel
ViewModel是MVVM框架的核心模块负责动态管理数据模型并通过`cc.director.emit`通知游戏内的节点组件状态变化。它是数据模型的包装器,提供了数据绑定、监听和通知的功能。
### VMBase
VMBase是所有VM组件的基类实现了基础的数据绑定功能。其他VM组件如VMLabel、VMState等都继承自VMBase。它提供了路径监听、值变化回调等核心功能。
### VM组件类型
- **VMCustom**:通用组件,可自定义绑定任意组件的属性
- **VMLabel**:专门用于文本显示,支持模板语法和格式化
- **VMState**:根据数据值控制节点状态(激活、显示、颜色等)
- **VMProgress**:用于进度条显示,支持双向绑定
- **VMEvent**:在值变化时触发事件,调用其他组件的方法
- **VMParent**用于定义局部范围的ViewModel数据
**Section sources**
- [MvvmInfo.md](file://doc/mvvm/MvvmInfo.md#L14-L29)
- [VMBase.md](file://doc/mvvm/VMBase.md#L1-L38)
## 数据模型注册与管理
### 数据模型注册
通过`VM.add(data, 'tag')`方法注册数据模型,其中`data`是要绑定的数据对象,`tag`是该数据模型的唯一标识标签。注册后该数据模型将被VMManager管理可以通过标签进行访问和操作。
```typescript
// 构建数据对象
let data = {
name: 'user',
gold: 12200,
info: {
id: 0
}
}
// 创建VM对象并添加到VMManager进行管理标记为'user'标签
VM.add(data, 'user');
```
### 数据模型管理API
- `add(data, tag)`创建并添加ViewModel对象
- `get(tag)`获取指定标签的ViewModel实例
- `remove(tag)`移除指定标签的ViewModel对象
- `setValue(path, value)`:设置值(支持全局路径)
- `addValue(path, value)`:累加值
- `getValue(path, defaultValue)`:获取值(支持默认值)
**Section sources**
- [MvvmInfo.md](file://doc/mvvm/MvvmInfo.md#L30-L51)
- [ViewModelScript.md](file://doc/mvvm/ViewModelScript.md#L20-L67)
## UI组件与数据绑定机制
### VMCustom组件
VMCustom是通用的绑定组件可以绑定任意组件的任意属性。在编辑器中挂载VMCustom组件后需要设置以下属性
- **Controller**:启用后支持双向绑定
- **Watch Path**:要监听的数据路径
- **Component Name**:要绑定的组件名称
- **Component Property**:要绑定的组件属性
- **refreshRate**刷新频率仅在Controller启用时生效
### VMLabel组件
VMLabel专门用于文本显示支持模板语法和多种格式化方式。其主要特性包括
- 支持单路径和多路径监听
- 使用`{{0}}``{{1}}`等模板语法
- 支持多种格式化:`int`(整数)、`fix(n)`(小数位数)、`kmbt`(千位分隔)、`per`(百分比)等
### VMState组件
VMState根据数据值控制节点状态可以实现条件显示、颜色变化等功能。主要配置包括
- **Watch Path**:监听的数据路径
- **Condition**:判断条件(如等于、大于等)
- **Value Action**:满足条件时执行的操作(如节点激活、可见性、不透明度、颜色等)
### VMProgress组件
VMProgress用于进度条显示需要设置两个监听路径最小值和最大值。其配置与VMCustom类似但专门针对进度条组件。
**Section sources**
- [VMCustom.md](file://doc/mvvm/VMCustom.md#L1-L17)
- [VMLabel.md](file://doc/mvvm/VMLabel.md#L1-L33)
- [VMState.md](file://doc/mvvm/VMState.md#L1-L41)
- [VMProgress.md](file://doc/mvvm/VMProgress.md#L1-L14)
## UI自动更新机制
### 事件驱动更新
当数据模型的值发生变化时ViewModel会通过`cc.director.emit`触发事件通知所有监听该路径的组件进行更新。这种事件驱动的机制确保了数据变化能够实时反映到UI上。
```mermaid
flowchart TD
A[修改数据模型] --> B{数据变化}
B --> C[ViewModel检测到变化]
C --> D[cc.director.emit触发事件]
D --> E[VM组件接收到通知]
E --> F[更新UI显示]
```
**Diagram sources**
- [ViewModelScript.md](file://doc/mvvm/ViewModelScript.md#L69-L107)
### 双向绑定
通过启用VMCustom组件的Controller功能可以实现UI到数据的反向绑定。例如当用户拖动进度条时不仅可以更新UI显示还可以自动更新对应的数据模型值。
### 局部数据管理
对于局部组件可以继承VMParent组件来管理局部数据。这种方式适用于弹窗等需要独立数据管理的场景。VMParent会在`onLoad`时自动将`*.name`形式的路径中的`*`替换为实际的ViewModel标签。
**Section sources**
- [MvvmInfo.md](file://doc/mvvm/MvvmInfo.md#L30-L51)
- [VMParent.md](file://doc/mvvm/VMParent.md#L1-L23)
## 编辑器配置与使用示例
### HInfoComp组件分析
HInfoComp是英雄信息显示组件展示了如何通过VM组件实现数据绑定
```mermaid
classDiagram
class HInfoComp {
+h_uuid : number
+heroNodes : Node[]
+update_data(uuid : number)
+load_all_hero(uuid : number)
+next_hero()
+prev_hero()
}
HInfoComp --> VMLabel : "使用"
HInfoComp --> VMProgress : "使用"
HInfoComp --> VMState : "使用"
```
**Diagram sources**
- [HInfoComp.ts](file://assets/script/game/map/HInfoComp.ts#L1-L343)
### SIconComp组件分析
SIconComp是技能图标组件展示了简单的数据绑定
```mermaid
classDiagram
class SIconCompComp {
+update_data(s_uuid : number)
}
SIconCompComp --> VMCustom : "使用"
```
**Diagram sources**
- [SIconComp.ts](file://assets/script/game/map/SIconComp.ts#L1-L27)
### 编辑器配置步骤
1. 在节点上添加VM组件如VMLabel、VMState等
2. 设置Watch Path为对应的数据路径`user.gold`
3. 配置组件特定属性如VMLabel的模板格式
4. 运行游戏数据变化将自动反映到UI上
### 数值格式化示例
```typescript
// 在VMLabel中使用模板语法
// {{0:int}} 显示整数
// {{0:fix(2)}} 显示两位小数
// {{0:kmbt}} 使用K/M/B/T单位缩写
// {{0:per}} 显示百分比
// {{0:sep}} 使用千位分隔符
```
### 节点状态切换示例
```typescript
// 使用VMState控制节点状态
// Condition: value >= 30
// Value Action: NODE_VISIBLE
// Watch Nodes: 指定要控制的节点
```
### 进度条更新示例
```typescript
// 使用VMProgress更新进度条
// Watch Path Arr: [currentValue, maxValue]
// Component Name: ProgressBar
// Component Property: progress
```
**Section sources**
- [HInfoComp.ts](file://assets/script/game/map/HInfoComp.ts#L1-L343)
- [SIconComp.ts](file://assets/script/game/map/SIconComp.ts#L1-L27)
## 高级功能与最佳实践
### VMEvent组件
VMEvent组件可以在值变化时触发事件调用其他组件的方法。适用于需要自定义处理逻辑的场景如数值变化时播放动画、播放音效等。
### VMModify组件
VMModify组件提供了便捷的数据修改方法可以通过事件调用实现数据的增减操作
- `vAddInt`:增加整数
- `vSubInt`:减少整数
- `vMulInt`:乘以整数
- `vDivInt`:除以整数
- `vString`:设置字符串
- `vNumber`:设置数值
### 性能优化建议
1. 合理使用局部数据管理VMParent避免全局数据的过度监听
2. 控制刷新频率refreshRate避免不必要的频繁更新
3. 及时移除不再使用的ViewModel防止内存泄漏
4. 避免过度嵌套使用VMParent以免影响性能
### 调试技巧
1. 使用`VM.get(tag)`获取ViewModel实例进行调试
2. 通过`vm.active = false`临时关闭通知功能进行问题排查
3. 利用编辑器的组件配置界面直观地查看和修改绑定关系
**Section sources**
- [VMEvent.md](file://doc/mvvm/VMEvent.md#L1-L21)
- [VMModify.md](file://doc/mvvm/VMModify.md#L13-L29)