无代码平台这两年非常火,号称不用写代码就能搭建应用。但它背后的原理是什么?可视化拖拽是怎么变成可运行的应用的?数据模型、页面渲染、逻辑执行、权限控制这些核心模块是怎么工作的?本文从底层原理出发,剖析无代码平台的架构和核心机制,帮你真正理解它是怎么运作的。

一、无代码平台是什么

无代码(No-Code)平台是一种允许用户通过可视化界面、拖拽操作和配置化方式创建应用的工具,不需要传统的编程。用户不需要写代码,通过配置数据表、拖拽页面组件、设置业务规则,就能搭建出管理系统、表单收集、工作流等应用。

无代码和低代码(Low-Code)的区别:无代码完全不需要写代码,面向业务人员;低代码允许写代码扩展,面向开发者。但两者的底层原理有很多共通之处,本文主要讲无代码,但很多原理也适用于低代码。

典型的无代码平台包括:Airtable、Notion、宜搭、简道云、明道云、氚云等。它们的表现形式不同,但核心架构类似。

二、整体架构

一个典型的无代码平台由以下几个核心层组成:

  1. 元数据层:描述应用结构的数据,包括数据表定义、字段定义、页面配置、流程配置、权限配置等
  2. 引擎层:根据元数据渲染和运行应用的核心,包括数据引擎、页面渲染引擎、流程引擎、规则引擎、权限引擎
  3. 存储层:存储元数据和业务数据,通常用关系型数据库
  4. 界面层:可视化的设计器和运行时界面

无代码平台的核心思想是"元数据驱动":用户在可视化界面上的所有配置,最终都被保存为元数据(通常是JSON),运行时引擎读取元数据,动态渲染出可运行的应用。这和传统的代码生成不一样,代码生成是生成代码然后部署,无代码是引擎直接解释执行元数据,修改配置后即时生效。

三、元数据模型

元数据是无代码平台的核心,它描述了应用的一切。

1. 数据模型元数据

描述数据表和字段的结构,比如:

{
  "table": "orders",
  "name": "订单表",
  "fields": [
    {"name": "order_no", "type": "text", "label": "订单号", "required": true},
    {"name": "customer", "type": "relation", "label": "客户", "ref_table": "customers"},
    {"name": "amount", "type": "number", "label": "金额", "precision": 2},
    {"name": "status", "type": "select", "label": "状态", "options": ["待付款", "已付款", "已发货", "已完成"]},
    {"name": "created_at", "type": "datetime", "label": "创建时间"}
  ]
}

用户在界面上创建表、添加字段、设置字段类型和属性,这些操作最终被保存为这样的元数据。引擎根据元数据在数据库中创建对应的表结构,或者用通用的表结构存储(比如EAV模型)。

2. 页面元数据

描述页面的布局和组件,比如:

{
  "page": "order_list",
  "name": "订单列表",
  "layout": "list",
  "components": [
    {"type": "search_bar", "fields": ["order_no", "status"]},
    {"type": "table", "data_source": "orders", "columns": ["order_no", "customer", "amount", "status", "created_at"]},
    {"type": "pagination", "page_size": 20}
  ]
}

用户拖拽组件到画布上、设置组件属性,这些操作被保存为页面元数据。运行时页面引擎读取元数据,动态渲染出对应的页面。

3. 流程元数据

描述业务流程和审批流,比如:

{
  "workflow": "order_approval",
  "trigger": "order.created",
  "steps": [
    {"type": "approval", "assignee": "department_manager", "action": "approve_or_reject"},
    {"type": "condition", "if": "amount > 10000", "then": [{"type": "approval", "assignee": "finance_manager"}]},
    {"type": "update_record", "set": {"status": "已审批"}}
  ]
}

用户通过可视化的流程设计器配置审批节点、条件分支、通知等,保存为流程元数据。流程引擎在运行时解释执行这些元数据。

4. 权限元数据

描述角色和权限,比如哪些角色可以查看哪些数据、可以执行哪些操作。

四、数据引擎

数据引擎负责处理业务数据的增删改查,是无代码平台的核心之一。

1. 数据存储方案

无代码平台的数据存储有两种主要方案:

一种是专用表模式:每个用户创建的数据表对应数据库中的一张真实表,字段对应真实列。这种方式性能好,查询效率高,但表结构变更(加字段、改类型)需要DDL操作,大规模多租户场景下管理复杂。

另一种是通用表模式(EAV或JSON列):用一张通用的表存储所有业务数据,数据存在JSON列中,或者用实体-属性-值(EAV)模型。这种方式灵活,加字段不需要改表结构,适合多租户场景,但查询性能差,复杂查询需要特殊处理。

很多平台采用混合方案:核心字段用真实列,扩展字段用JSON列,兼顾性能和灵活性。

2. 查询引擎

用户在页面上配置的筛选、排序、搜索,最终被查询引擎翻译成SQL或其他查询语言。查询引擎要处理字段映射、权限过滤、关联查询、聚合统计等。

比如用户在列表页配置了"状态=已付款"的筛选,查询引擎会把这个条件翻译成WHERE子句,同时加上权限过滤条件(比如只能看自己部门的数据),然后执行查询,返回结果给页面渲染。

3. 数据校验

数据引擎在写入数据前会根据字段配置做校验,比如必填校验、格式校验(手机号、邮箱)、范围校验、唯一性校验等。这些校验规则保存在元数据中,写入时自动执行,不需要用户写代码。

五、页面渲染引擎

页面渲染引擎负责把页面元数据变成用户看到的界面。

1. 组件系统

无代码平台有一套预设的组件库,包括输入框、下拉选择、日期选择、表格、表单、图表、按钮等。每个组件有统一的接口:接收props(配置和数据)、渲染UI、触发事件。

用户在设计器中拖拽组件,实际上是在页面元数据中添加一个组件配置。运行时渲染引擎遍历组件列表,根据组件类型找到对应的组件实现,传入配置和数据,渲染出UI。

2. 数据绑定

组件需要和数据绑定,比如表格组件绑定到某个数据表,输入框绑定到某个字段。渲染引擎处理数据绑定,把业务数据注入到组件中,用户操作组件时(比如输入文字、选择选项),引擎把数据写回数据模型。

数据绑定是响应式的:数据变化时组件自动更新,组件操作时数据自动更新。这和前端框架(Vue、React)的响应式原理类似,但无代码平台的绑定是通过元数据配置的,不需要用户写代码。

3. 事件和动作

用户操作组件会触发事件(比如按钮点击、表单提交、值变化),每个事件可以配置一系列动作(比如打开弹窗、提交数据、跳转页面、发送通知)。渲染引擎监听组件事件,触发时执行配置的动作链。

动作链是一个有序的动作列表,支持条件判断、循环、异步等待等。比如"提交按钮点击"事件可以配置:先校验表单→再提交数据→成功后弹出提示→然后刷新列表→最后关闭弹窗。

六、流程引擎

流程引擎负责执行业务流程和审批流,是无代码平台的重要组成部分。

1. 流程定义和执行

流程引擎读取流程元数据,按照定义的步骤依次执行。每个步骤有特定的类型(审批、通知、条件、更新数据、调用API等),引擎根据类型执行对应的操作。

审批步骤会创建一个审批任务,分配给指定的审批人,等待审批人操作。审批人通过或拒绝后,引擎根据结果决定流程走向:通过则进入下一步,拒绝则结束流程或退回。

2. 条件分支

流程支持条件分支,根据数据的值决定走哪条路径。比如金额大于10000需要财务审批,否则不需要。流程引擎在运行时计算条件表达式,选择对应的分支执行。

条件表达式通常是一种简单的脚本语言或可视化的条件配置,引擎解析并执行这些表达式。

3. 流程状态管理

流程引擎需要管理流程实例的状态:当前在哪个步骤、等待谁审批、已经执行了哪些步骤。这些状态保存在数据库中,流程引擎根据状态恢复执行,支持暂停、恢复、终止、退回等操作。

七、规则引擎

规则引擎负责执行业务规则,比如字段联动、自动计算、数据校验、触发动作等。

1. 字段联动

表单中一个字段的值变化时,其他字段跟着变化。比如选择了"客户类型=VIP","折扣"字段自动变成0.8。这些联动规则保存在元数据中,规则引擎监听字段变化,执行对应的规则,更新其他字段的值。

2. 自动计算

有些字段是计算出来的,比如"总价=单价*数量"。规则引擎在相关字段变化时自动重新计算计算字段的值,不需要用户手动输入。

3. 触发器

当数据发生变化时(新增、修改、删除),可以触发一系列动作,比如发送通知、更新其他表的数据、调用外部API。触发器规则保存在元数据中,数据引擎在数据变化时调用规则引擎执行触发器。

八、权限引擎

权限引擎控制谁能看什么数据、能做什么操作,是企业级应用的关键。

1. 角色和权限

无代码平台通常用基于角色的访问控制(RBAC):创建角色,给角色分配权限(查看、新增、编辑、删除、导出等),把用户分配到角色中。用户登录后,权限引擎根据用户的角色判断他能执行什么操作。

2. 数据权限

除了功能权限,还有数据权限:不同角色能看到的数据范围不同。比如普通员工只能看自己的数据,部门经理能看本部门的数据,管理员能看所有数据。

数据权限通常通过条件过滤实现:用户查询数据时,权限引擎在查询条件中加上数据范围限制(比如"部门=当前用户部门"),用户只能看到符合条件的数据。

3. 字段权限

更细粒度的权限是字段级权限:某些角色只能看某些字段,不能看敏感字段(比如薪资、身份证号)。权限引擎在返回数据时,根据用户角色过滤掉无权查看的字段。

九、多租户架构

大部分无代码平台是SaaS模式,多个企业(租户)共用一套系统。多租户架构有三种模式:

  1. 独立数据库:每个租户一个数据库,隔离性最好但成本高
  2. 共享数据库独立Schema:同一个数据库,每个租户一个Schema,隔离性和成本折中
  3. 共享数据库共享表:所有租户共用表,用tenant_id区分数据,成本最低但隔离性差

大部分无代码平台采用第三种方式,用tenantid隔离数据,查询时自动加上tenantid条件,确保租户之间数据隔离。元数据也按租户隔离,每个租户的配置互不影响。

十、无代码平台的局限

理解了原理,就能理解无代码平台的局限。

1. 灵活性受限

无代码平台的功能受限于预设的组件、规则和流程。如果需求超出了平台预设的能力,就无法实现,或者实现起来非常别扭。比如复杂的算法、特殊的交互、深度定制的UI,无代码很难做到。

2. 性能问题

元数据驱动的方式比原生代码多了一层解释执行的开销,数据量大、逻辑复杂时性能可能不够。尤其是通用表存储模式,查询效率不如专用表。

3. 数据锁定

数据存在平台的数据库中,导出和迁移可能不方便,长期使用有供应商锁定的风险。

4. 复杂业务逻辑难以表达

简单的增删改查和审批流无代码很擅长,但复杂的业务逻辑(比如复杂的计算、状态机、集成多个系统)用无代码表达起来很困难,维护成本高。

十一、写在最后

无代码平台的核心原理是元数据驱动:用户的可视化配置被保存为元数据,运行时引擎解释执行元数据,动态渲染出应用。数据引擎、页面渲染引擎、流程引擎、规则引擎、权限引擎协同工作,让用户不用写代码就能搭建应用。

理解了底层原理,就能更好地使用无代码平台:知道它擅长什么、不擅长什么,在合适的场景用合适的工具。无代码不是要取代开发者,而是让业务人员能自己搭建简单应用,让开发者从重复的CRUD中解放出来,专注于更复杂的问题。

未来无代码平台会越来越强大,AI的加入可能会让应用搭建更智能、更自然。但无论怎么发展,理解它的底层原理,才能更好地利用它、甚至构建自己的无代码平台。

希望这篇原理剖析能帮你深入理解无代码平台是怎么工作的。如果有问题欢迎在评论区交流讨论。