Vue 3 的 reactive 不生成组件树,需先构建树形结构再包裹;状态应解耦管理;增删改须走响应式通道;属性变更自动同步渲染与 DSL 导出。

Vue 3 的 reactive 本身不“生成”组件树,它只让已有结构具备响应性。低代码平台的组件树配置,核心是先定义清晰的 DSL(如 JSON Schema),再用 reactive 包裹整个树对象,配合合理状态分离与安全更新机制,才能支撑拖拽、嵌套、属性编辑等交互。
组件树数据必须提前建好,不能靠 reactive “自动变树”
后端或画布导出的通常是扁平化节点列表(带 id、parentId、type 等字段)。reactive 不会帮你递归组装父子关系——你得自己构建树形结构:
- 用
Map建立id → node映射,便于快速查找 - 遍历一次原始数据,把每个节点推入其
parentId对应父节点的children数组(确保children初始化为reactive([])) - 找出根节点(
parentId为空、null或0),作为树入口 - 最后用
reactive包裹整个根对象:const componentTree = reactive(buildTreeFromFlatList(schema))
展开/选中/禁用等 UI 状态要和数据模型解耦
别把 isExpanded: true、checked: true 直接写进组件节点里。否则每次点击都会触发整棵树的依赖更新,性能差且逻辑混乱:
- 用独立的
reactive(new Set())管理展开 ID 集合,模板中用expandedIds.has(node.id)控制子节点渲染 - 用
ref([])或reactive({ checkedIds: new Set(), disabledIds: new Set() })管理多类状态 - 若使用
el-tree,需显式配置:props="{ children: 'children', label: 'label', disabled: 'disabled' }",并用v-model:checkedKeys绑定你的响应式 ID 列表
增删改操作必须走响应式通道,不能绕过 reactive
直接 node.children.push(newNode) 在某些场景下可能失效(比如 children 是普通数组而非 reactive 数组);深层赋值如 tree.nodes[0].props.label = '新标题' 虽可行但难维护:
立即学习“前端免费学习笔记(深入)”;
- 所有子节点数组都应初始化为
reactive([]),新增时用children.push(reactive(newNode)) - 提供统一的工具函数,如
updateNodeById(id, { props, style }),内部递归查找并安全赋值 - 删除节点时,用
children.splice(index, 1)或children = children.filter(n => n.id !== id),保持响应链完整 - 拖拽调整顺序时,用
moveNode(sourceId, targetId, position)封装移动逻辑,避免手动操作索引出错
组件属性变更需同步影响渲染与 DSL 导出
用户在右侧属性面板修改某个按钮的 text 或 size,不仅要实时更新画布,还要确保导出的 JSON Schema 也同步更新:
- 属性编辑器绑定的是
selectedNode.props(已由 reactive 代理),修改即响应 - 导出 DSL 时,直接序列化
componentTree即可,无需额外转换 - 如需做默认值清理或格式标准化(如移除空
style、合并重复 class),可在导出前调用精简函数,不破坏响应式源数据


















