# MVVM框架 **本文档引用的文件** - [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) ## 目录 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)