低代码与无代码
低代码不是"不用写代码",而是"只写必要的代码"——把重复的、模板化的、可配置的部分交给平台,把独特的、复杂的、差异化的部分留给开发者。
1. 概念辨析
1.1 什么是低代码 / 无代码
| 概念 | 英文 | 目标用户 | 写代码量 | 典型场景 |
|---|---|---|---|---|
| 无代码 | No-Code | 业务人员(零技术背景) | 0 | 表单收集、简单审批流、数据展示 |
| 低代码 | Low-Code | 专业开发者 + 技术型业务人员 | 少量(核心逻辑、复杂交互) | 后台管理系统、CRM、ERP、中台 |
关键区别:无代码追求"可视化拖拽完成一切";低代码承认"有些场景必须写代码",但尽量减少代码量。
一句话总结:无代码是给业务人员用的 Excel 升级版;低代码是给开发者用的效率工具。
1.2 发展脉络
1990s 2000s 2014 2018+ 2022+
│ │ │ │ │
RAD 工具 BPM 工作流 Forrester 提出 国内外平台爆发 AI + 低代码
(PowerBuilder (流程引擎) "Low-Code" OutSystems Copilot/通义
Oracle Forms) 概念诞生 Mendix/宜搭 灵码集成
为什么现在火:
- 企业数字化转型需求井喷,但程序员供给远不足
- 后台管理系统高度同质化(90% 是增删改查 + 审批流)
- 前端框架成熟,为低代码引擎提供了基础设施
2. 核心原理:低代码平台是怎么跑起来的
2.1 整体架构
┌─────────────────────────────────────────────────────┐
│ 设计器(Designer) │
│ 拖拽组件 → 配置属性 → 编排逻辑 → 实时预览 │
└────────────────────┬────────────────────────────────┘
│ 产出 Schema(JSON)
▼
┌─────────────────────────────────────────────────────┐
│ 引擎(Engine) │
│ 解析 Schema → 渲染组件 → 执行逻辑 → 管理状态 │
└────────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ 物料(Materials) │
│ 组件库(表格/表单/图表)+ 区块模板 + 页面模板 │
└─────────────────────────────────────────────────────┘
三个核心角色:
| 角色 | 干什么 | 类比 |
|---|---|---|
| 设计器 | 可视化编辑界面,拖拽搭建页面 | Figma / Photoshop |
| 引擎 | 解析设计器产出的配置,渲染成真实页面 | 浏览器渲染引擎 |
| 物料 | 可被设计器使用的组件/模板/区块 | 设计组件库 |
2.2 协议:Schema(页面描述规范)
低代码平台的核心是 Schema——一份 JSON,完整描述一个页面长什么样、有哪些交互、数据从哪里来。
{
"componentName": "Page",
"props": { "title": "用户管理" },
"children": [
{
"componentName": "SearchForm",
"props": {
"fields": [
{ "name": "keyword", "label": "关键词", "type": "input" },
{ "name": "status", "label": "状态", "type": "select",
"options": [
{ "label": "启用", "value": 1 },
{ "label": "禁用", "value": 0 }
]
}
],
"onSearch": { "type": "ref", "target": "userTable.refresh" }
}
},
{
"componentName": "Table",
"id": "userTable",
"props": {
"columns": [
{ "key": "name", "title": "姓名" },
{ "key": "email", "title": "邮箱" },
{ "key": "status", "title": "状态",
"render": { "type": "tag", "map": { "1": "启用", "0": "禁用" } }
}
],
"dataSource": { "type": "api", "url": "/api/users", "method": "GET" },
"pagination": { "pageSize": 20 }
}
}
]
}
Schema 的本质:用声明式数据结构替代命令式代码。相当于"用 JSON 写 React/Vue 组件"。
常见协议标准:
- 阿里巴巴 LowCodeEngine 规范:国内事实标准,组件可跨平台复用
- App Router / Amis:百度开源的 JSON 渲染方案
- 各厂家自研协议:宜搭、明道云、轻流各自定义了私有 Schema
2.3 引擎:如何把 Schema 变成真实页面
引擎是低代码平台的运行时核心,一个极简版引擎的实现:
// 引擎核心:递归渲染组件树
class LowCodeEngine {
constructor(components) {
// components: 注册的物料组件映射表
// { "Button": ButtonComponent, "Table": TableComponent, ... }
this.components = components;
}
// 解析并渲染 Schema
render(schema, context) {
const { componentName, props, children, id } = schema;
// 1. 查找对应的 React/Vue 组件
const Component = this.components[componentName];
if (!Component) {
console.warn(`未注册组件: ${componentName}`);
return null;
}
// 2. 解析 props 中的表达式/数据源/事件绑定
const resolvedProps = this.resolveProps(props, context);
// 3. 处理事件绑定(onClick → 真实函数)
const eventProps = this.resolveEvents(props, context);
// 4. 递归渲染子组件
const renderedChildren = children?.map(child =>
this.render(child, context)
);
// 5. 返回真实 VNode
return h(Component, {
...resolvedProps,
...eventProps,
key: id,
}, renderedChildren);
}
// 解析属性中的动态表达式
resolveProps(props, context) {
const result = {};
for (const [key, value] of Object.entries(props)) {
// 处理 JS 表达式: { "type": "expression", "code": "state.total * 100" }
if (value?.type === 'expression') {
// 在沙箱中执行表达式,注入 state/props/context
result[key] = this.evaluateExpression(value.code, context);
}
// 处理数据源: { "type": "api", "url": "/api/users" }
else if (value?.type === 'api') {
result[key] = this.resolveDataSource(value, context);
}
// 普通值直接使用
else {
result[key] = value;
}
}
return result;
}
// 在安全沙箱中执行表达式
evaluateExpression(code, context) {
const sandbox = { state: context.state, $ctx: context };
const fn = new Function(...Object.keys(sandbox), `return (${code})`);
return fn(...Object.values(sandbox));
}
// 解析数据源(API / 变量 / 引用)
async resolveDataSource(ds, context) {
if (ds.type === 'api') {
const res = await fetch(ds.url, { method: ds.method || 'GET' });
return res.json();
}
if (ds.type === 'variable') {
return context.state[ds.key];
}
}
// 事件绑定转换为真实函数
resolveEvents(props, context) {
const events = {};
for (const [key, value] of Object.entries(props)) {
if (key.startsWith('on') && typeof value === 'object') {
// { "type": "action", "action": "openModal", "params": {...} }
events[key] = () => context.actions[value.action]?.(value.params);
}
}
return events;
}
}
引擎要解决的核心问题:
| 问题 | 解决方案 |
|---|---|
| 组件如何注册和发现 | 物料中心:组件元数据 + npm 包映射 |
| Schema 到组件的映射 | 按 componentName 动态查找并渲染 |
| 动态表单/表格 | 通过配置驱动(columns/fields 数组 → 组件渲染) |
| 组件间通信 | 全局状态 Store + 事件总线 + 数据源引用 |
| 表达式/逻辑 | 沙箱执行(new Function / eval),注入上下文 |
| 布局 | 内置布局组件(Row/Col/Tab/Card),嵌套渲染 |
2.4 设计器:可视化搭建怎么实现
设计器界面的三个核心区域:
┌──────────────┬──────────────────┬──────────────┐
│ 物料面板 │ │ 属性面板 │
│ │ │ │
│ 📦 基础组件 │ 画布 Canvas │ 组件名称 │
│ - Button │ │ 尺寸/颜色 │
│ - Input │ [拖拽放置区域] │ 数据绑定 │
│ - Table │ │ 事件配置 │
│ │ 实时预览效果 │ 条件渲染 │
│ 📦 布局组件 │ │ │
│ - Row/Col │ │ │
│ - Card │ │ │
│ │ │ │
│ 📦 业务组件 │ │ │
│ - UserSelect│ │ │
└──────────────┴──────────────────┴──────────────┘
拖拽的实现(以 React DnD 为例):
// 拖拽的基本流程
// 1. 物料面板中的组件标记为 DragSource
// 2. 画布区域标记为 DropTarget
// 3. 放置时,往 Schema JSON 中插入新节点,引擎即时渲染
// 简化示意
function Canvas() {
const [schema, setSchema] = useState(initialSchema);
const handleDrop = (componentMeta, position) => {
// 在 Schema 树中插入新节点
const newNode = createNode(componentMeta);
const newSchema = insertNode(schema, newNode, position);
setSchema(newSchema);
// 引擎立即根据新 Schema 重新渲染
};
return (
<DropTarget onDrop={handleDrop}>
<Engine schema={schema} />
</DropTarget>
);
}
属性面板的核心:根据组件元数据动态生成配置表单。
// 组件的元数据描述
const ButtonMeta = {
componentName: 'Button',
props: [
{ name: 'text', label: '按钮文字', type: 'string', default: '确定' },
{ name: 'type', label: '类型', type: 'select',
options: ['primary', 'default', 'danger', 'link'] },
{ name: 'size', label: '尺寸', type: 'select',
options: ['large', 'middle', 'small'] },
{ name: 'disabled', label: '是否禁用', type: 'boolean', default: false },
// 高级配置
{ name: 'visible', label: '条件可见', type: 'expression',
placeholder: "{{ state.status === 'active' }}" },
{ name: 'onClick', label: '点击事件', type: 'event' },
],
};
// 属性面板根据元数据动态渲染表单
function PropsEditor({ meta, value, onChange }) {
return (
<Form>
{meta.props.map(prop => (
<FormItem key={prop.name} label={prop.label}>
{prop.type === 'string' && <Input value={value[prop.name]} />}
{prop.type === 'select' && <Select options={prop.options} />}
{prop.type === 'boolean' && <Switch checked={value[prop.name]} />}
{prop.type === 'expression' && (
<CodeEditor language="javascript" placeholder={prop.placeholder} />
)}
{prop.type === 'event' && <EventHandler config={value[prop.name]} />}
</FormItem>
))}
</Form>
);
}
2.5 出码:Schema 如何变成真实代码
低代码平台的三种出码策略:
| 策略 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| 运行时解析 | Schema 保存到数据库,引擎运行时动态渲染 | 修改即时生效、无需构建 | 性能有损耗、SEO 不友好 |
| 编译出码 | Schema → 源码(React/Vue 文件)→ 构建部署 | 性能最优、可独立部署 | 每次修改需要重新出码+构建 |
| 混合模式 | 核心页面出码部署,动态页面运行时渲染 | 灵活平衡 | 架构复杂度更高 |
编译出码的本质:Schema JSON → AST → 代码字符串。
// Schema 片段
const schema = {
componentName: 'Page',
children: [
{ componentName: 'Button', props: { text: '提交', type: 'primary' } }
]
};
// 出码结果
// import { Button } from 'antd';
// export default function Page() {
// return <Button type="primary">提交</Button>;
// }
// 出码器的核心是一个递归的代码生成器
function generateCode(schema) {
const { componentName, props, children } = schema;
// 1. 属性转代码字符串
const propsStr = generateProps(props);
// 2. 子组件递归生成
const childrenStr = children?.map(generateCode).join('\n') || '';
// 3. 拼接 JSX
return `<${componentName}${propsStr}>${childrenStr}</${componentName}>`;
}
3. 主流平台与方案
3.1 国内外平台全景
| 平台 | 类型 | 开源 | 特点 | 适用场景 |
|---|---|---|---|---|
| OutSystems | 低代码 | 否 | 企业级、强建模、全栈 | 大型企业核心系统 |
| Mendix | 低代码 | 否 | 云原生、模型驱动、协作能力强 | 中大型企业 |
| Retool | 低代码 | 否 | 面向开发者、组件丰富、快速搭建内部工具 | 内部工具/管理后台 |
| Appsmith | 低代码 | 是 | Retool 开源替代、自部署 | 内部工具/数据面板 |
| 阿里 LowCodeEngine | 低代码引擎 | 是 | 引擎级开源、可自建平台 | 二次开发/自建低代码平台 |
| 宜搭 | 低代码 | 否 | 阿里出品、钉钉深度集成 | 企业内部应用 |
| 简道云 | 无代码 | 否 | 帆软出品、表单流程强 | 数据收集/审批流 |
| 明道云 | 无代码 | 否 | 零代码 APaaS、工作表驱动 | 中小企业全套业务系统 |
| 飞书多维表格 | 无代码 | 否 | 表格界面、AirTable 竞品 | 轻量级协作管理 |
| 微搭 | 低代码 | 否 | 腾讯出品、微信生态集成 | 小程序/企业微信应用 |
| 轻流 | 无代码 | 否 | BPM 流程引擎突出 | 审批流/业务流程 |
| Zion | 无代码 | 否 | 国内首个在线教育型无代码平台 | 小程序/H5 快速搭建 |
3.2 开源引擎方案对比
| 引擎 | 组织 | 技术栈 | 核心思路 | 是否支持出码 |
|---|---|---|---|---|
| LowCodeEngine | 阿里 | React + Node | 引擎 + 设计器分离,物料可插拔 | 是 |
| Amis | 百度 | React | JSON 配置渲染,零设计器依赖 | 否(纯运行时) |
| Formily | 阿里 | React/Vue | 表单领域低代码,解决复杂表单场景 | 否 |
| PagePlug | 社区 | Vue | Appsmith 的 Vue 版 | 否 |
| ToolJet | 社区 | React | 开源低代码,自部署 | 是 |
| NocoDB | 社区 | Vue | AirTable 开源替代 | 否 |
| Budibase | 社区 | Svelte | 开源低代码,全栈 | 否 |
3.3 Amis:JSON 配置即页面
百度 Amis 是"运行时解析式"低代码的典型代表——不产出源码,JSON 直接即是运行中的页面。
{
"type": "page",
"title": "用户管理",
"body": [
{
"type": "crud",
"api": "/api/users",
"columns": [
{ "name": "id", "label": "ID" },
{ "name": "name", "label": "姓名" },
{ "name": "email", "label": "邮箱" },
{
"name": "status",
"label": "状态",
"type": "mapping",
"map": { "1": "<span class='text-success'>启用</span>", "0": "<span class='text-danger'>禁用</span>" }
}
],
"filter": {
"body": [
{ "type": "input-text", "name": "keyword", "label": "关键词", "placeholder": "搜索姓名/邮箱" },
{ "type": "select", "name": "status", "label": "状态", "options": [{"label": "启用","value":1},{"label": "禁用","value":0}] }
]
}
}
]
}
核心设计思想:
- 一切皆组件:页面是组件、表单是组件、表格是组件、按钮也是组件
- 每个组件有
type字段声明自己的类型 - 组件通过嵌套(
body/columns/filter)形成树状结构 - 引擎按 type 查找对应 React 组件并渲染
Amis 的适用边界:
- ✅ 标准后台 CRUD 页面 —— 极快,JSON 写完即上线
- ✅ 表单密集型场景 —— 120+ 表单组件开箱即用
- ❌ 高度定制 UI —— JSON 配置无法替代 CSS 像素级调整
- ❌ 复杂交互逻辑 —— 联级联动超出 3 层时 JSON 配置痛苦
4. 后端低代码怎么工作
低代码不只是前端的事——后端逻辑同样需要"低代码化"。
4.1 数据模型驱动
传统开发流程:数据库建表 → 写后端代码 → 写接口 → 写前端页面
低代码流程: 在界面上定义数据模型 → 自动生成数据表 + CRUD 接口 + 默认页面
# 在一个低代码平台上定义"客户"数据模型
模型名称: Customer
字段:
- name: string(50), 必填, 显示名="客户名称"
- contact: string(20), 显示名="联系电话"
- level: enum(普通/VIP/SVIP), 默认="普通"
- source: string(100), 显示名="客户来源"
- created_at: datetime, 自动填充=当前时间
平台根据这个模型自动生成:
- 数据库表
customer - REST 接口:
GET/POST/PUT/DELETE /api/customers - 默认列表页 + 详情页 + 表单页
4.2 流程引擎
审批流和业务流程是低代码的核心场景:
请假审批流程:
员工提交 ──→ 部门主管审批 ──→ 人事审批 ──→ 归档
│ │
└── 驳回 ─────────┘ (回到提交人)
# 低代码平台中的流程定义(BPMN 简化版)
流程名称: 请假审批
触发条件: 新增请假记录
节点:
- 节点1: 部门主管审批
审批人: ${当前用户.直属上级}
审批方式: 或签(任意一人通过即可)
超时: 48小时自动通过
分支:
- 通过 → 节点2
- 驳回 → 结束(通知提交人)
- 节点2: 人事审批
审批人: HR部门所有人
审批方式: 会签(所有人通过)
分支:
- 通过 → 节点3
- 驳回 → 节点1(退回到上一步)
- 节点3: 归档
自动操作:
- 更新请假记录状态 = 已通过
- 扣减年假余额 -${请假天数}
- 发送通知给提交人
流程引擎的核心机制:
| 概念 | 说明 |
|---|---|
| 节点 | 流程中的一个步骤(审批/填写/分支/自动操作) |
| 流转条件 | 决定从当前节点走向哪个节点的规则 |
| 审批人解析 | 支持固定人/角色/部门/上级/脚本动态计算 |
| 会签/或签 | 会签=所有人都要审批;或签=任一人审批即可 |
| 超时处理 | 超时后自动通过/驳回/转交 |
| 回退/取回 | 支持退回到任意已处理节点 |
| 流程版本 | 修改流程定义时,已运行的实例不受影响 |
4.3 逻辑编排
对于"获取数据 → 处理 → 写入"这类逻辑,低代码平台提供可视化函数编排:
┌─────────────┐
触发(HTTP 请求)──→ │ 查询用户信息 │
└──────┬──────┘
│
┌──────▼──────┐ 是
│ 是否为VIP? │────────→ 计算折扣 20%
└──────┬──────┘
│ 否
┌──────▼──────┐
│ 计算折扣 0% │
└──────┬──────┘
│
┌──────▼──────┐
│ 生成订单 │
└─────────────┘
本质上是把以下代码可视化:
async function createOrder(req) {
const user = await db.user.findById(req.userId);
const discount = user.level === 'VIP' ? 0.2 : 0;
return db.order.create({ ...req.body, discount });
}
5. 低代码 vs 传统开发:什么时候该用
5.1 适用场景
| 场景 | 推荐度 | 原因 |
|---|---|---|
| 后台管理系统(CRUD) | ⭐⭐⭐⭐⭐ | 高度同质化,低代码效率提升 5-10 倍 |
| 表单审批流程 | ⭐⭐⭐⭐⭐ | 流程引擎开箱即用 |
| 数据看板/大屏 | ⭐⭐⭐⭐ | 图表组件拖拽即可,无需手写 ECharts |
| 内部运营工具 | ⭐⭐⭐⭐ | 需求多变但不要求 UI 精致 |
| 活动落地页 | ⭐⭐⭐ | 模板化程度高,快速上线 |
| 原型验证/MVP | ⭐⭐⭐⭐ | 快速出可交互版本给老板/客户看 |
| 移动端简单应用 | ⭐⭐⭐ | 配合小程序容器可以快速出 App |
5.2 不适用场景
| 场景 | 原因 |
|---|---|
| C 端高交互产品(电商首页、社交App) | UI 定制化极高,低代码无法做到像素级还原 |
| 复杂算法/数据处理 | 可视化编排效率反而不如直接写代码 |
| 已有复杂老系统 | 改造迁移成本远超收益 |
| 高性能场景(游戏、实时协同) | 引擎运行时开销不可忽略 |
| 需要极致 SEO | 运行时解析式低代码对 SEO 不友好 |
| 对稳定性要求极高的核心系统 | 低代码平台的 Bug 不在你掌控范围内 |
5.3 决策框架
这个功能/页面适合用低代码吗?
├─ 是不是增删改查 + 表格 + 表单?
│ └─ 是 → 用低代码(效率碾压手写)
│
├─ 是不是审批流 / 工作流?
│ └─ 是 → 用低代码的流程引擎
│
├─ UI 是否要求像素级定制?
│ └─ 是 → 必须手写(低代码做不到)
│
├─ 有没有复杂的、非标准的前端交互?
│ └─ 是 → 手写,或在低代码中嵌入自定义组件
│
├─ 是否频繁迭代、需求变化快?
│ └─ 是 → 低代码(改配置比重构代码快)
│
└─ 团队是否具备专业前端能力?
├─ 有 → 自建或基于开源引擎定制
└─ 无 → 采购成熟低代码平台
6. 开发者视角:低代码改变了什么
6.1 开发者角色的转变
传统开发者: 手写每一行代码 → 你就是代码的唯一生产者
低代码开发者: 写物料组件 + 写引擎扩展 + 写复杂逻辑 + 解决平台无法覆盖的场景
└── 你是低代码平台的"增强者",而不是被平台替代
6.2 使用低代码平台的三种姿势
| 姿势 | 说明 | 适合谁 |
|---|---|---|
| 纯用平台 | 完全在平台上搭建,不写任何代码 | 业务人员、初级开发者 |
| 平台 + 自定义组件 | 标准功能用平台,特殊需求自己开发组件嵌入 | 有前端能力的小团队 |
| 自建低代码平台 | 基于开源引擎(LowCodeEngine/Amis)搭建自己的低代码平台 | 有前端架构能力的大团队 |
6.3 前端开发者与低代码的关系
前端开发者的价值不会被低代码取代,但会重新分配:
重复劳动(📉 被替代) 不可替代(📈 价值更高)
├─ 手写第 50 个表格页面 ├─ 设计低代码引擎架构
├─ 手写第 100 个表单校验 ├─ 开发高质量物料组件
├─ 手写标准 CRUD 接口 ├─ 解决低代码平台无法覆盖的复杂场景
└─ 复制粘贴审批流代码 ├─ 低代码平台 + AI 结合的前沿探索
└─ 性能调优、安全加固、定制化改造
建议:
- 初级前端:掌握 1-2 个低代码平台使用,提升交付速度
- 中高级前端:理解低代码引擎原理,能自建或深度定制
- 架构师:能判断什么场景用低代码、什么场景手写,做正确的技术选型
7. 发展趋势
| 趋势 | 说明 |
|---|---|
| AI + 低代码 | 自然语言描述需求 → AI 生成 Schema → 平台渲染。Copilot / 通义灵码已开始集成 |
| 垂直领域下沉 | 不再做"通用低代码",而是做"CRM 低代码""供应链低代码""政务低代码" |
| Pro-Code 打通 | 平台提供 VS Code 插件,专业开发者在 IDE 中直接编辑 Schema 或出码产物 |
| 协作能力增强 | 产品出原型 → 设计师出设计稿 → 开发者出组件 → 业务人员搭页面,全角色在同一平台协作 |
| 混合渲染 | 出码部署核心页面 + 运行时解析动态页面,兼顾性能和灵活性 |
8. 动手试一试
| 平台 | 上手方式 | 推荐理由 |
|---|---|---|
| 阿里 LowCodeEngine | 官网 Demo 直接体验 + 源码 GitHub | 理解引擎原理的最佳入口 |
| Amis | 在线编辑器直接写 JSON 看效果 | 感受 JSON 配置式开发 |
| Appsmith | 注册即用,免费 | 体验完整低代码开发流程 |
| 简道云 | 注册免费版 | 体验无代码表单+流程 |
建议学习路径:
- 先用简道云搭一个请假审批应用(感受无代码)
- 再用 Appsmith 搭一个数据看板(感受低代码)
- 在 Amis 在线编辑器中写 JSON 配置生成页面(理解 Schema 驱动)
- 阅读 LowCodeEngine 源码的
engine和designer部分(理解内核)