引言
本文件面向VTJ平台的"项目模型架构",系统性阐述ProjectModel、BlockModel、NodeModel三类核心数据模型的设计理念、实现细节与协作关系。文档聚焦以下目标:
- 解释项目模型的层次结构、数据继承关系与职责划分
- 说明ProjectModel如何管理项目配置、页面列表与全局设置
- 介绍BlockModel的区块定义、复用机制与版本管理
- 阐述NodeModel的节点抽象、属性系统与事件绑定
- 提供模型间协作关系图、数据流转过程与状态管理模式
- 给出具体代码示例路径、数据结构定义与使用场景
项目结构
VTJ的核心模型位于packages/core模块中,采用"协议定义 + 模型实现 + 类型声明"的分层组织方式:
- 协议层:定义跨层共享的数据契约(如ProjectSchema、BlockSchema、NodeSchema)
- 模型层:提供可序列化的领域模型(ProjectModel、BlockModel、NodeModel)
- 类型层:导出TS类型声明,便于上层消费与IDE提示
graph TB
subgraph "协议层"
PJS["ProjectSchema
项目协议"] BJS["BlockSchema
区块协议"] NJS["NodeSchema
节点协议"] end subgraph "模型层" PM["ProjectModel
项目模型"] BM["BlockModel
区块模型"] NM["NodeModel
节点模型"] end subgraph "类型层" PDT["project.d.ts"] BDT["block.d.ts"] NDT["node.d.ts"] end PJS --> PM BJS --> BM NJS --> NM PM --> PDT BM --> BDT NM --> NDT
项目协议"] BJS["BlockSchema
区块协议"] NJS["NodeSchema
节点协议"] end subgraph "模型层" PM["ProjectModel
项目模型"] BM["BlockModel
区块模型"] NM["NodeModel
节点模型"] end subgraph "类型层" PDT["project.d.ts"] BDT["block.d.ts"] NDT["node.d.ts"] end PJS --> PM BJS --> BM NJS --> NM PM --> PDT BM --> BDT NM --> NDT
核心组件
本节概览三大模型的职责边界与关键能力。
-
ProjectModel(项目模型)
- 职责:统一管理项目级配置、页面树、区块库、API与元数据;提供文件生命周期操作(创建/更新/移动/复制/删除)、依赖管理、国际化与环境变量配置、发布与出码等
- 关键点:以事件总线驱动变更通知;提供toDsl序列化能力;维护当前激活文件currentFile
-
BlockModel(区块模型)
- 职责:封装可复用组件的定义与行为,包括状态、方法、计算属性、生命周期、侦听器、CSS、属性、事件、插槽、数据源、节点树等
- 关键点:节点树管理(增删改移、克隆、层级锁定/解锁);toDsl序列化并带版本号;事件广播
-
NodeModel(节点模型)
- 职责:抽象单个UI节点(组件或HTML标签),承载属性、事件、指令、插槽与子节点树
- 关键点:父子关系与兄弟顺序维护;属性/事件/指令的增删改查;可见性与锁定传播;toDsl序列化
架构总览
三大模型形成"项目-区块-节点"的树形分层结构,ProjectModel持有页面与区块文件列表,每个文件内部嵌套BlockModel,BlockModel内部维护NodeModel树。

详细组件分析
ProjectModel 分析
- 设计要点
- 以静态属性列表控制可更新字段,确保update的可控性与一致性
- 通过事件常量与事件总线对外广播变更,便于上层订阅与响应
- 页面树支持目录与布局混合结构,提供递归遍历、查找父节点、移动与复制等能力
- 区块与页面互转:将页面保存为区块,或将区块作为页面DSL使用
- 配置管理:项目配置、UniApp配置、全局配置、国际化与环境变量均提供原子setter
- 数据结构与复杂度
- 页面查找:递归遍历 pages,最坏O(N)
- 页面移动:先定位父节点O(N),再splice,整体O(N)
- 依赖/API/Meta去重:基于名称或ID匹配,平均O(M)
- 使用场景
- 新建页面并自动激活
- 将页面保存为区块复用
- 更新项目配置或国际化设置
- 发布与出码流程触发
sequenceDiagram
participant UI as "设计器/UI"
participant PM as "ProjectModel"
participant EM as "事件总线"
participant BM as "BlockModel"
UI->>PM : "创建页面"
PM->>PM : "生成ID/默认DSL"
PM->>EM : "广播页面变更事件"
PM-->>UI : "返回页面对象"
UI->>PM : "保存为区块"
PM->>BM : "基于页面DSL创建BlockModel"
PM->>PM : "写入blocks列表"
PM->>EM : "广播区块变更事件"
PM-->>UI : "完成"
BlockModel 分析
- 设计要点
- 以normalAttrs集中管理可序列化字段,toDsl输出包含版本号
- 节点树管理:支持在指定位置插入、移动、克隆与删除;支持层级锁定/解锁传播
- 行为与元数据:方法、计算属性、生命周期、侦听器、CSS、属性、事件、插槽、注入、数据源等
- 数据结构与复杂度
- 节点插入/删除/移动:基于数组索引操作,O(K)(K为兄弟节点数)
- 节点克隆:深度克隆DSL后重建NodeModel,O(D)(D为节点深度)
- isChild判断:递归遍历子树,最坏O(N)
- 使用场景
- 在区块内新增/调整组件布局
- 定义组件属性、事件与插槽
- 管理组件状态与侦听器
flowchart TD
Start(["开始"]) --> AddNode["添加节点到目标位置"]
AddNode --> HasTarget{"是否有目标节点?"}
HasTarget --> |否| Append["追加到根节点末尾"]
HasTarget --> |是| Pos{"位置类型"}
Pos --> |left/top| InsertBefore["插入到目标前"]
Pos --> |right/bottom| InsertAfter["插入到目标后"]
Pos --> |inner| AppendChild["作为目标子节点"]
InsertBefore --> Done(["结束"])
InsertAfter --> Done
AppendChild --> Done
Append --> Done
NodeModel 分析
- 设计要点
- 节点唯一标识与来源标记;父子关系与兄弟顺序维护
- 属性、事件、指令采用专用模型封装,支持增删改查与序列化
- 可见性与锁定支持向下传播,保证批量操作一致性
- 数据结构与复杂度
- 子节点增删改:数组索引操作,O(S)(S为兄弟节点数)
- 节点移动:在父节点兄弟数组中重排,O(S)
- 销毁:递归销毁子树并解除父子关系,O(N)
- 使用场景
- 在设计器中拖拽/排序组件
- 动态绑定事件与指令
- 批量锁定/解锁与显隐控制
sequenceDiagram
participant UI as "设计器/UI"
participant NM as "NodeModel"
participant Parent as "父节点"
participant EM as "事件总线"
UI->>NM : "插入到某节点之后"
NM->>Parent : "请求在父节点中插入"
Parent->>Parent : "兄弟数组splice"
Parent->>EM : "广播节点变更事件"
Parent-->>UI : "完成"
依赖分析
- 模型间耦合
- ProjectModel持有BlockModel实例(通过文件DSL),但不直接持有NodeModel
- BlockModel直接持有NodeModel数组,形成树状组合关系
- NodeModel通过父指针向上回溯,形成双向关联
- 事件与工具
- 三大模型均通过事件总线对外广播变更,便于解耦
- 工具入口导出事件总线与通用工具,供模型层使用
graph LR
EM["事件总线"] --> PM["ProjectModel"]
EM --> BM["BlockModel"]
EM --> NM["NodeModel"]
PM --> BM
BM --> NM
性能考虑
- 序列化与版本
- toDsl输出包含版本号,便于增量比较与缓存失效
- 页面树清理:在导出前清理DSL中的冗余字段,降低体积
- 树操作
- 节点移动与插入基于数组索引,建议在批量操作时合并为单次事件广播
- 锁定/可见性传播为递归操作,避免在超大树上频繁触发
- 事件风暴
- 大规模节点变更时,优先使用静默模式(silent)减少事件风暴
- 查询优化
- 页面查找与去重逻辑基于线性扫描,建议在高频场景引入索引结构(如按名称/ID的Map)
故障排查指南
- 常见问题
- 页面/区块未找到:检查ID或名称是否重复,确认existXxxName与exclude列表
- 节点移动异常:确认目标节点存在且允许插入(目录/布局节点需特殊处理)
- 事件未触发:确认silent参数与事件常量是否正确传递
- 排查步骤
- 使用toDsl导出最小化DSL,定位问题节点
- 逐步撤销最近变更,确认问题触发点
- 检查事件总线订阅者是否遗漏或重复注册
结论
VTJ的项目模型架构以清晰的分层与强约束的协议为基础,通过ProjectModel、BlockModel、NodeModel三者协同,实现了从项目配置到页面/区块再到组件级别的全链路建模。其事件驱动与序列化能力为设计器、渲染器与生成器提供了稳定的数据通道。建议在实际工程中:
- 严格遵循协议字段,避免越界更新
- 在批量操作时合理使用静默模式与事件合并
- 对超大页面树进行必要的索引与懒加载策略
参考资料
VTJ.PRO 是一个开源的、AI 驱动的 Vue 3 企业级应用开发平台。它通过 AI 智能体与可视化编排实现高效开发,并支持导出标准 Vue 代码以避免平台锁定。更多信息请访问:
- 📘 官方文档:vtj.pro/
- 🌐 在线平台:app.vtj.pro/
- 📦 开源仓库:gitee.com/newgateway/...