核心概念
引言
本篇"核心概念"旨在为VTJ低代码平台建立坚实的理论基础,围绕以下主题展开:低代码平台的基本原理、DSL(领域特定语言)的概念与作用、项目模型架构的设计思想;深入阐释ProjectModel、BlockModel、NodeModel三者的数据结构设计理念与相互关系;说明MVVM架构模式在平台中的落地方式、事件驱动机制与观察者模式的实现;介绍多端适配的原理、渲染器架构与代码生成机制。通过架构图与流程图,帮助开发者建立对平台工作原理与设计哲学的系统性认知。
项目结构
VTJ采用多包(monorepo)组织方式,核心能力分布在多个子包中:
- 核心模型与协议:@vtj/core(ProjectModel、BlockModel、NodeModel及其Schema)
- 设计器引擎:@vtj/designer(Engine、Designer、Simulator、Assets等)
- 渲染器与Provider:@vtj/renderer(Provider、createRenderer、createLoader、路由与全局配置)
- 解析器:@vtj/parser(模板与脚本解析,提取事件、指令、侦听器等)
- 示例与测试:dev、docs等
graph TB
subgraph "核心"
CORE["@vtj/core
模型与协议"] end subgraph "设计器" DESIGNER["@vtj/designer
Engine/Designer/Simulator"] end subgraph "渲染" RENDERER["@vtj/renderer
Provider/createRenderer"] end subgraph "解析" PARSER["@vtj/parser
模板/脚本解析"] end subgraph "示例与文档" DEV["dev
渲染器测试示例"] DOCS["docs
Wiki与概念文档"] end CORE --> DESIGNER CORE --> RENDERER CORE --> PARSER DESIGNER --> RENDERER RENDERER --> DEV DOCS --> DESIGNER DOCS --> RENDERER
模型与协议"] end subgraph "设计器" DESIGNER["@vtj/designer
Engine/Designer/Simulator"] end subgraph "渲染" RENDERER["@vtj/renderer
Provider/createRenderer"] end subgraph "解析" PARSER["@vtj/parser
模板/脚本解析"] end subgraph "示例与文档" DEV["dev
渲染器测试示例"] DOCS["docs
Wiki与概念文档"] end CORE --> DESIGNER CORE --> RENDERER CORE --> PARSER DESIGNER --> RENDERER RENDERER --> DEV DOCS --> DESIGNER DOCS --> RENDERER
核心组件
本节聚焦平台的三大核心数据结构:ProjectModel(项目模型)、BlockModel(区块模型)、NodeModel(节点模型)。它们共同构成DSL的运行时载体,支撑设计器与渲染器的协作。
- ProjectModel:统一管理项目元数据、页面与区块文件、依赖、API、元数据、国际化与环境变量等,提供CRUD与树形导航能力,并通过事件总线对外广播状态变更。
- BlockModel:承载单个区块的DSL,包含状态、生命周期、方法、计算属性、侦听器、CSS、props/emit/slots/dataSources、节点树等,提供节点增删改移动与状态/函数/属性/事件/指令/数据源的管理。
- NodeModel:描述单个组件或HTML标签的DSL节点,包含id/name/from、可见性/锁定、children/props/events/directives、slot等,提供父子关系维护与DSL序列化。
classDiagram
class ProjectModel {
+id : string
+name : string
+platform : PlatformType
+pages : PageFile[]
+blocks : BlockFile[]
+currentFile : PageFile/BlockFile
+dependencies : Dependencie[]
+apis : ApiSchema[]
+meta : MetaSchema[]
+update(schema, silent)
+active(file, silent)
+deactivate(silent)
+createPage(page, parentId, silent)
+updatePage(page, silent)
+movePageTo(id, parentId, silent)
+createBlock(block, silent)
+updateBlock(block, silent)
+removeBlock(id, silent)
+setApi(item, silent)
+removeApi(name, silent)
}
class BlockModel {
+id : string
+name : string
+state : BlockState
+lifeCycles : Record
+methods : Record
+computed : Record
+watch : BlockWatch[]
+css : string
+props : Array
+emits : Array
+slots : Array
+dataSources : Record
+nodes : NodeModel[]
+locked : boolean
+update(schema, silent)
+toDsl(version)
+addNode(node, target, position, silent)
+removeNode(node, silent)
+move(node, target, position, silent)
+setState(name, value, silent)
+setFunction(type, name, value, silent)
+setWatch(watch, silent)
+setProp(prop, silent)
+setEmit(emit, silent)
+setSlot(slot, silent)
+setInject(inject, silent)
+setDataSource(source, silent)
}
class NodeModel {
+id : string
+name : string
+from : NodeFrom
+invisible : boolean
+locked : boolean
+children : NodeModel[]|string|JSExpression
+slot? : NodeSlot
+props : Record
+events : Record
+directives : DirectiveModel[]
+update(schema, silent)
+setChildren(children, silent)
+setSlot(slot, silent)
+setProp(name, value, default, silent)
+setEvent(event, silent)
+setDirective(dir, silent)
+appendChild(node, silent)
+insertAfter(node, silent)
+insertBefore(node, silent)
+movePrev(silent)
+moveNext(silent)
+toDsl()
}
ProjectModel --> BlockModel : "管理页面/区块DSL"
BlockModel --> NodeModel : "包含节点树"
架构总览
VTJ采用"模型-渲染-设计器"三层协同架构:
- 模型层:以ProjectModel/BlockModel/NodeModel为核心,承载DSL与状态,提供事件广播。
- 渲染层:Provider负责加载依赖、物料、路由与全局配置,createRenderer根据DSL生成可渲染组件。
- 设计器层:Engine协调ProjectModel/BlockModel/NodeModel与Provider/Simulator/Assets,绑定事件流,实现所见即所得的编辑体验。
graph TB
subgraph "模型层"
PM["ProjectModel"]
BM["BlockModel"]
NM["NodeModel"]
end
subgraph "渲染层"
PR["Provider"]
CR["createRenderer"]
CL["createLoader"]
end
subgraph "设计器层"
ENG["Engine"]
DES["Designer"]
SIM["Simulator"]
end
PM --> ENG
BM --> ENG
NM --> ENG
ENG --> PR
PR --> CR
CR --> CL
ENG --> DES
ENG --> SIM
详细组件分析
事件驱动与观察者模式
平台广泛采用事件总线(mitt封装)实现松耦合通信:
- 模型变更事件:PROJECT_CHANGE、BLOCK_CHANGE、NODE_CHANGE、HISTORY_CHANGE等。
- 设计器事件:文件激活/关闭、发布、出码、历史加载等。
- 渲染器事件:按需触发渲染上下文更新。
sequenceDiagram
participant UI as "设计器UI"
participant ENG as "Engine"
participant EM as "事件总线(emitter)"
participant SRV as "Service"
participant PR as "Provider"
participant RND as "Renderer"
UI->>ENG : 用户操作(新增/修改节点)
ENG->>EM : 触发EVENT_NODE_CHANGE
EM-->>ENG : 分发事件
ENG->>SRV : 保存文件DSL
ENG->>PR : 更新Provider上下文
PR->>RND : 重建渲染器
RND-->>UI : 重新渲染
MVVM架构在平台中的应用
- Model:ProjectModel/BlockModel/NodeModel承载数据与行为。
- View:渲染器根据DSL生成Vue组件树,支持内置指令与自定义指令。
- ViewModel:Engine与Provider协调模型与视图,Designer作为交互入口,Simulator提供预览与调试。
flowchart TD
Start(["开始:用户在设计器中操作"]) --> Change["模型变更(节点/属性/事件/指令)"]
Change --> Save["保存到服务端/本地缓存"]
Save --> Reload["Provider加载DSL并创建渲染器"]
Reload --> Render["渲染器生成组件树并挂载"]
Render --> Preview["Simulator预览/调试"]
Preview --> End(["结束:页面/区块生效"])
DSL(领域特定语言)的概念与作用
- DSL是对页面/区块的结构化描述,包含节点树、状态、生命周期、方法、侦听器、指令、事件等。
- 通过toDsl()/update()实现模型与DSL之间的双向转换,保证设计器与渲染器的一致性。
- 解析器从模板/脚本中抽取事件、指令、侦听器等,反向完善DSL。
flowchart TD
Dsl["DSL(JSON/JS对象)"] --> ToModel["toDsl() -> 模型"]
ToModel --> Designer["设计器编辑"]
Designer --> Update["update() -> 模型变更"]
Update --> ToDsl["toDsl() -> 输出DSL"]
ToDsl --> Parser["解析器抽取事件/指令/侦听器"]
Parser --> Dsl
项目模型架构设计思想
- 分层数据结构:ProjectModel聚合页面与区块,支持树形导航与页面/区块CRUD。
- 事件驱动:通过统一事件总线广播项目级变更,确保设计器与渲染器同步。
- 多端抽象:通过平台类型与全局配置,抽象不同端(web/h5/uniapp)差异。
flowchart TD
Create["创建页面/区块"] --> UpdatePages["更新pages/blocks树"]
UpdatePages --> Emit["广播EVENT_PROJECT_PAGES_CHANGE/EVENT_PROJECT_BLOCKS_CHANGE"]
Emit --> Save["持久化到服务/本地"]
Save --> Load["Provider加载DSL并初始化"]
Load --> Render["渲染器渲染"]
多端适配原理与渲染器架构
- Provider负责根据运行模式(设计/源码/预览)加载依赖、物料与路由。
- 支持uniapp/web/h5等平台差异,通过全局配置、国际化、环境变量与路由策略适配。
- createRenderer结合createLoader动态加载依赖DSL,实现按需渲染。
sequenceDiagram
participant APP as "应用"
participant PR as "Provider"
participant SRV as "Service"
participant RND as "Renderer"
APP->>PR : 初始化(传入mode/adapter/router/globals)
PR->>SRV : 加载项目DSL
SRV-->>PR : 返回ProjectSchema
PR->>PR : 解析依赖/物料/路由
PR->>RND : createRenderer(dsl, loader)
RND-->>APP : 返回可挂载组件
代码生成机制
- 出码触发:Engine监听PROJECT_GEN_SOURCE事件,调用service.genSource生成源码。
- 生成范围:通常针对项目pages集合与当前ProjectModel DSL进行打包。
- 结果落盘:生成物写入目标目录,供构建/发布流程使用。
sequenceDiagram
participant UI as "设计器UI"
participant ENG as "Engine"
participant SRV as "Service"
UI->>ENG : 触发出码(genSource)
ENG->>SRV : genSource(projectDslWithPages)
SRV-->>ENG : 返回生成结果
ENG-->>UI : 显示生成状态/产物
事件绑定与指令系统
- 事件绑定:设计器通过事件绑定器选择事件名与处理函数,支持修饰符与校验。
- 指令系统:支持v-if/v-show/v-for/v-html等内置指令,以及v-model派生(根据物料描述推导)。
- 侦听器:支持JSFunction源与处理函数,支持深监听与立即执行。
flowchart TD
Select["选择事件/指令"] --> Bind["绑定到NodeModel"]
Bind --> Parse["解析器抽取事件/指令/侦听器"]
Parse --> Update["更新DSL并触发模型变更"]
Update --> Render["渲染器重新渲染"]
依赖分析
- 模型层依赖:@vtj/core提供ProjectModel/BlockModel/NodeModel与协议定义。
- 设计器层依赖:@vtj/designer依赖@vtj/core与@vtj/renderer,协调Engine/Designer/Simulator。
- 渲染层依赖:@vtj/renderer依赖@vtj/core的协议与DSL,提供Provider与渲染器工厂。
- 解析层依赖:@vtj/parser解析模板与脚本,产出事件/指令/侦听器等DSL片段。
graph LR
CORE["@vtj/core"] --> DESIGNER["@vtj/designer"]
CORE --> RENDERER["@vtj/renderer"]
DESIGNER --> RENDERER
PARSER["@vtj/parser"] --> CORE
PARSER --> DESIGNER
性能考量
- 事件风暴防护:通过事件静默更新(silent)减少不必要的广播与重渲染。
- 懒加载与按需加载:Provider按运行模式加载依赖与物料,避免全量加载。
- 缓存策略:Provider对URL DSL进行缓存,降低重复请求成本。
- 渲染优化:通过上下文模式与组件懒加载,减少首屏压力。
故障排查指南
- 事件未触发:确认事件名称与监听绑定是否一致,检查事件总线注册顺序。
- DSL不一致:检查toDsl()/update()调用链,确保模型与DSL双向同步。
- 渲染失败:核对Provider初始化参数(mode/adapter/router/globals),确认依赖与物料加载成功。
- 指令/事件解析异常:检查解析器正则与表达式生成逻辑,确保事件名与处理函数匹配。
结论
VTJ通过清晰的模型层(ProjectModel/BlockModel/NodeModel)、完善的事件驱动与观察者模式、灵活的渲染器与Provider架构,以及强大的解析器与多端适配能力,构建了低代码平台的坚实理论基础与工程实践。理解这些核心概念与组件关系,有助于开发者高效地进行二次开发、扩展与集成。
附录
- 项目模型与区块模型概念文档:[项目模型和区块模型]
- 渲染器测试示例(DSL输入样例):[渲染器测试视图]
- HTML到节点解析测试:[HTML解析测试]
参考资料
VTJ.PRO 是一个开源的、AI 驱动的 Vue 3 企业级应用开发平台。它通过 AI 智能体与可视化编排实现高效开发,并支持导出标准 Vue 代码以避免平台锁定。更多信息请访问:
- 📘 官方文档:vtj.pro/
- 🌐 在线平台:app.vtj.pro/
- 📦 开源仓库:gitee.com/newgateway/...