前言
今年大半年的时间,我都在参与公司内部低代码平台的搭建,从 Schema 协议设计、渲染器实现,到拖拽设计器、出码方案,基本把低代码前端这块完整趟了一遍。低代码在这两年经历了从”概念炒作”到”务实落地”的转变,我们平台目前已经支撑了内部几十个运营后台和活动页。这篇文章把最核心的两块内容——Schema 驱动和拖拽设计器——的实现思路整理出来,附上可参考的代码骨架和踩过的坑,作为今年的技术总结之一。
1. 低代码兴起与适用场景
先泼一盆冷水:低代码不是银弹。它兴起的原因很朴素——企业里存在大量逻辑简单、重复度高、对个性化要求低的页面需求:运营活动页、表单问卷、后台 CRUD 列表页、数据看板。这类需求占比其实很高(我们统计过内部需求池,超过 60% 的前端需求属于此类),但每一个都要走”提需求 → 排期 → 开发 → 测试 → 上线”的完整流程,成本严重不成比例。
低代码的解法是把这类页面的生产从”写代码”降级为”配置搭建”,把前端从重复劳动中解放出来去写真正有价值的复杂业务。同时它也让运营、产品这些不写代码的角色具备了有限的自助搭建能力。
对应的,低代码的不适用场景也很明确:强交互、复杂状态、极致性能要求的核心业务(比如编辑器、游戏、复杂中台业务),以及 UI 高度定制的设计驱动型页面。给低代码平台定义清楚边界,比堆功能更重要。这也是我今年最大的经验教训之一。
2. 核心思想:Schema 驱动 UI
2.1 用 JSON 描述页面
低代码平台整个体系的基石是一个约定好的 Schema 协议:**页面 = 一棵组件树,每个节点描述”用什么组件 + 传什么 props + 子节点是什么”**。一个简单的页面 Schema 长这样:
1 | { |
设计 Schema 协议时我给自己定了三条原则:
- 协议先于实现。Schema 是平台资产,渲染器、设计器、出码器都是它的消费者。先把协议的字段、版本、扩展机制定义清楚,后面所有能力都长在这棵树上。
- 节点携带稳定 id。设计器里选中组件、属性回填、事件绑定全靠 id 定位,没有 id 的 Schema 是不可编辑的。
- 留好逃生舱。一定会有协议覆盖不了的需求,所以要留自定义组件、自定义代码块(事件里的 actionType 之外允许挂 JS 片段)这类逃生通道,否则平台会被”这个需求实现不了”耗死口碑。
2.2 渲染器:一个递归函数就够了
Schema 渲染器的实现思路简单到出乎意料:维护一个组件注册表,把组件名映射到真实组件,然后对 Schema 树做递归渲染。Vue 版核心代码不到 50 行:
1 | // registry.js:物料注册表,物料包安装时注册进来 |
1 | <!-- Renderer.vue --> |
递归渲染器之外,还需要一套动作系统处理事件:Schema 里的 onClick: { actionType: 'submitForm' } 被派发到统一的 dispatcher,由它执行提交表单、跳转链接、打开弹窗、发送请求等预置动作。逻辑尽量收敛在动作协议里,实在复杂才允许逃生舱里的自定义代码。运行时渲染器加上动作系统,就是低代码平台的”内核”,我们平台的移动端和 PC 端渲染器共用同一套 Schema,只是物料实现不同。
3. 拖拽设计器:三区架构

3.1 物料面板、画布、属性面板
设计器(编辑器)是低代码平台体验的核心,业界成熟方案基本都收敛在”三区布局”:
- 左:物料面板。按分类展示可拖入的组件(布局、表单、展示、媒体),本质是物料元信息的可拖拽列表;
- 中:画布。渲染 Schema 的预览态,叠加选中、悬停、拖入位置提示等编辑态交互,内部跑的就是第 2 节的渲染器(加了编辑态开关);
- 右:属性面板。根据选中组件的物料元信息(propsSchema)动态渲染出配置表单,改的是当前选中节点的 Schema。
三个区共享一个中心状态:当前页面的 Schema 树 + 当前选中的组件 id。所有交互最终都归结为对这棵树的操作(插入节点、移动节点、修改节点 props),这就是为什么 Schema 协议设计得好,设计器就好做。
3.2 HTML5 Drag & Drop API 实现拖拽
物料拖入画布,我选择原生 HTML5 Drag & Drop 实现(不依赖 dnd 库,可控性强)。完整链路分三段:拖起时携带组件标识 → 拖动时计算落点 → 落下时插入 Schema。
第一段,物料面板的每个组件设置 draggable,并在 dragstart 里把组件名放进 dataTransfer:
1 | // 物料面板:开始拖拽时,声明要拖的组件类型 |
第二段,画布在 dragover 里阻止默认行为(不阻止则浏览器不允许 drop),并根据鼠标位置计算”应该插入到哪个节点的哪个位置”:
1 | // 画布:拖动经过时计算落点 |
第三段,drop 时把新组件节点插入 Schema 树:
1 | canvasEl.addEventListener('drop', (e) => { |
画布内已有组件之间互相拖动换位(重排)复用同一套机制,只是 dragstart 来源是画布节点而不是物料面板,drop 时执行”删除旧位置 + 插入新位置”。
3.3 选中态与 outline 计算的坑
编辑态交互里,”选中组件的高亮框”看起来简单,坑却很多。最初我直接给每个组件容器加 outline: 1px solid,很快遇到三个问题:
- 组件根节点可能是内联元素或没有高度的空节点,outline 看不见或者形状诡异。解法是设计器约定”每个物料根节点必须是块级元素”,并在物料规范里作为 lint 规则检查;
- 高亮框遮挡子组件的 hover 和点击,导致嵌套组件只能选到外层。解法是把选中框从”组件自己的样式”改成独立覆盖层(overlay):一个绝对定位的图层浮在画布上方、
pointer-events: none,选中节点变化时读取目标节点的getBoundingClientRect(),把框画在覆盖层上。这样高亮永远不挡交互; - 滚动和缩放导致覆盖层错位。
getBoundingClientRect()返回的是视口坐标,画布滚动、画布被缩放(我们支持 50%~150% 缩放)后必须换算:overlayX = (rect.left - canvasRect.left) / zoom。更稳的做法是监听画布scroll事件、用上ResizeObserver,在任何布局变化后重算一次覆盖层。
覆盖层方案最终长这样:
1 | function syncOverlay() { |
另外还有一个细节值得记一笔:drop 目标容器的判定。嵌套布局里鼠标可能悬停在多层容器上,document.elementFromPoint 拿到的永远是最深元素,需要沿着 DOM 向上找最近的可容器化节点(有 children 能力的组件),否则会出现”拖进错误层级”的问题。
4. Schema 与出码
低代码平台绕不开的灵魂拷问:**Schema 存的是”配置”,但业务方常要”真代码”**——要么为了二次开发,要么为了平台解绑。出码(code generation)就是从 Schema 生成可维护的源码。
4.1 出码思路:AST 而非字符串拼接
出码的正确姿势是”数据 → AST → 代码”,而不是模板字符串拼接。以 Vue 代码为例,思路是把 Schema 树映射成 Vue 的模板 AST:每个组件节点对应一个元素节点,props 对应属性绑定,事件对应 @click 处理器声明,最后用 @vue/compiler 系列或 prettier 美化输出。
核心流程伪代码:
1 | function generateVueCode(schema) { |
生成出来的代码里,data、methods 都带好了骨架和注释,工程师拿过去接手就是普通 Vue 项目的开发体验。我们踩过最大的坑是缩进和空行控制:字符串拼接出来的代码格式混乱不可读,后来全部换成 AST + prettier 输出,可读性问题一次性解决。
4.2 出码与渲染器的关系:一体两面
架构上我建议把出码器理解为”渲染器的孪生兄弟”:两者消费同一份 Schema,一个在运行时解释执行,一个在构建时翻译成代码。它们必须共享同一套物料元信息(props 类型、事件定义),否则会出现”设计器里好好的,出码后表现不一致”的经典 bug。我们后来把 props 类型校验抽成了独立包,渲染器和出码器共用,不一致问题就消失了。
5. 写在 2022 年末:一点趋势展望
今年明显感觉到低代码的”配置驱动”思想正在外溢:Serverless 的编排、自动化工作流工具、甚至许多 SaaS 的规则引擎,本质都是 Schema 驱动。
AI 那边有个值得记下的新闻:上月底 OpenAI 放出了 ChatGPT,一句需求描述就能吐出像样的代码片段,我身边的前端群刷屏了三天。它离直接生成整页 Schema 还很远,但”自然语言 → 页面”这条路头一次有了能摸得到的进展。低代码解决的是”不写代码也能搭页面”,用户却还要学”拖拽 + 配置”这套心智;如果这条路走通,平台的交互入口可能会从画布变成对话框,届时用户跳过的不只是代码,还有这套学习成本——而 Schema 仍然是那个不变的中心资产。
写在最后
回顾整个低代码平台的实现,最核心的判断只有一个:Schema 协议是资产,渲染器、设计器、出码器都是它的消费者。把协议设计好,三件套的实现反而是水到渠成的事:渲染器是 50 行的递归,设计器是”一棵树 + 三块面板”,出码器是 AST 翻译。
踩坑最多的地方都在编辑态交互上:overlay 错位、elementFromPoint 的层级问题、拖拽落点的插入判定。这类问题没有现成轮子,值得多花时间打磨体验,因为设计器好不好用直接决定平台的口碑和存活。
明年的计划是把 Schema 的逻辑编排部分做深(可视化事件流),并小范围验证 AI 生成 Schema 的可行性。如果你也在做低代码平台,欢迎留言交流,这一年踩的坑能聊的还有很多。




