amis 开源项目解读
项目信息
项目名称:amis
项目描述:amis 是百度开源的前端低代码框架,通过 JSON 配置自动生成后台管理页面,拥有 237+ 组件、自研表达式引擎和完整的可视化编辑器。
核心特点:
- 670,000 行源代码
- 237+ 个前端组件(142 UI + 95 业务)
- 9 个 Monorepo 子包(5 层架构)
- 86+ 个编辑器插件
- Apache-2.0 开源许可
核心模块:
- L5:
amis-editor,可视化编辑器,拖拽构建页面; - L4:
amis,业务渲染,JSON → 页面; - L3:
amis-ui,基础组件,按钮/表单/表格; - L2:
amis-core,基础设施,工厂/Store/动作; - L1:
amis-formula,表达式引擎,公式/变量/过滤器;
- L5:
1. 项目概览
1.1 项目定位与核心价值
一句话定位:amis 是一个面向前端开发者和后端开发者的低代码前端框架,通过 JSON 配置就能自动生成各种后台管理页面(CRUD、表单、图表、仪表盘等),极大减少前端开发成本,甚至可以完全不需要了解前端技术。
解决的核心痛点:
- 后台页面重复开发:企业后台管理系统存在大量重复性工作(表单、表格、列表页),传统方式需要手写大量 HTML/CSS/JS,开发效率低。amis 将页面结构抽象为 JSON 配置,实现"配置即页面"。
- 前端人力资源瓶颈:大量后端开发者需要做后台管理系统但不熟悉前端技术。amis 允许后端开发者通过编写 JSON 配置来生成页面,降低前端门槛。
- UI 一致性难以保证:企业级后台系统需要统一的 UI 风格和交互规范。amis 内置了一套完整的 UI 组件库和主题系统,保证了所有页面风格统一。
目标用户群:
- 前端开发者:需要快速搭建后台管理系统的前端工程师
- 后端开发者:不熟悉前端但需要做后台页面的后端开发者
- 平台搭建者:需要集成低代码能力的 SaaS 平台开发者
1.2 目标场景与典型 Case
场景一 — 企业后台管理系统快速搭建:HR、财务、客户管理等内部系统,只需在 JSON 中描述页面结构,框架自动渲染。
场景二 — 低代码平台的核心渲染引擎:爱速搭(百度的低代码平台)使用 amis 作为底层渲染机制。
场景三 — 动态表单与配置化后台:SaaS 平台需要根据客户需求动态调整页面,改 JSON 配置即可改变页面,无需重新发布。
典型使用 Case(伪代码):
// 1. 定义 JSON Schema
const schema = {
type: "page",
title: "用户管理",
body: {
type: "crud",
api: "/api/users",
columns: [
{ name: "id", label: "ID" },
{ name: "name", label: "姓名" },
{ name: "email", label: "邮箱" }
]
}
};
// 2. 调用 render 函数
amis.render(schema, {}, { fetcher: myFetcher });
// 3. amis 自动将 JSON 渲染为完整的 React 交互页面1.3 核心技术亮点
- Schema 驱动渲染:页面完全由 JSON 配置描述,天然支持动态下发和实时修改
- 自研表达式引擎:安全沙箱执行,支持 80+ 内置公式函数,禁止 eval/Function
- MST 状态管理:基于 MobX State Tree 的树形状态管理系统,数据与 UI 一一对应
- 渲染器工厂模式:通过 @Renderer 装饰器注册自定义渲染器,支持异步加载
- 完整的低代码编辑器:WYSIWYG 可视化编辑,86+ 组件插件,拖拽构建页面
- Office 文档预览:自研 OpenXML 解析引擎,支持 xlsx/docx 在线预览
1.4 技术栈与选型对比
| 技术 | 选择 | 替代方案 | 选择原因 |
|---|---|---|---|
| 前端框架 | React 18 | Vue, Angular | 生态最成熟,社区最大 |
| 状态管理 | MST (MobX State Tree) | Redux, Zustand | 树形结构天然匹配组件树,内置 action 追踪 |
| 构建工具 | Vite 4 + Rollup | Webpack, FIS3 | 开发体验快,从 FIS3 逐步迁移 |
| 编译器 | SWC | Babel | 基于 Rust,编译速度快 20 倍 |
| 表达式引擎 | 自研 | eval/Function, Formula.js | 安全性(沙箱),可控性(自定义函数) |
| 样式方案 | SCSS + CSS Helper | Tailwind, CSS-in-JS | 兼容历史代码,工具类类似 Tailwind |
| Monorepo | Lerna + npm workspaces | Turborepo, pnpm | 团队熟悉度,稳定可靠 |
1.5 项目规模
| 维度 | 数据 |
|---|---|
| 总有效源文件 | ~3,820 |
| 源代码总行数 | ~670,000 |
| TypeScript/TSX 文件 | 1,892 (953 .ts + 939 .tsx) |
| SCSS 样式文件 | 321 |
| SVG 图标文件 | 390 |
| 前端组件总数 | 237+ (142 UI + 95 业务) |
| 编辑器插件数 | 86+ |
| Monorepo 子包数 | 9 (7 npm workspaces) |
| 当前版本 | 6.13.0 |
| 开源许可 | Apache-2.0 |
2. 整体架构设计 (Overall Architecture)
2.1 架构概述
amis 采用分层 Monorepo 架构,核心设计模式为 Schema 驱动的渲染引擎 + 渲染器工厂模式 + MST(MobX State Tree)状态管理。
系统从下到上分为 5 层:
- L1 - 表达式引擎层 (amis-formula):独立的词法分析、语法解析和表达式求值引擎,提供沙箱安全的公式计算能力
- L2 - 核心基础设施层 (amis-core):渲染器工厂、MST Store 系统、JSON Schema 解析、动作系统、主题/国际化基础设施
- L3 - UI 组件层 (amis-ui):142+ 基础 UI 组件(Button、Form、Table 等)、SCSS 样式系统、图标库
- L4 - 业务渲染层 (amis):95+ 业务渲染器(CRUD、Form Renderer、Table Renderer 等),将 JSON Schema 映射到 UI 组件
- L5 - 编辑器层 (amis-editor-core + amis-editor):可视化低代码编辑器,包括拖拽系统、属性面板、插件系统和实时预览
2.2 整体架构图
+===========================================================================+
| L5: 可视化编辑器层 |
| +-------------------------+ +------------------------------+ |
| | amis-editor | | amis-theme-editor-helper | |
| | [86+ Plugin] | | [主题编辑辅助] | |
| | [Builder] [Renderer] | +------------------------------+ |
| +------------+------------+ |
| | (依赖) |
| +------------v------------+ |
| | amis-editor-core | |
| | [DnD System] | |
| | [Plugin Manager 68KB] | |
| | [Inline Editor] | |
| | [Store Manager] | |
| +-------------------------+ |
+=============================+=============================================+
| (依赖)
+=============================v=============================================+
| L4: 业务渲染层 (amis) |
| +-----------------------------------------------------------------------+ |
| | Schema.ts (Type System) | Renderers (95+ 业务渲染器) | |
| | - SchemaFull.ts (27KB) | - Form/ (95+ 表单项渲染器) | |
| | - SchemaMinimal.ts (25KB) | - Table/ (旧版表格渲染器) | |
| | - Schema.ts | - Table2/ (新版表格渲染器) | |
| | - compat.ts (15KB) | - Action, CRUD, CRUD2, Dialog... | |
| +-----------------------------------------------------------------------+ |
+=============================+=============================================+
| (依赖)
+=============================v=============================================+
| L3: UI 组件层 (amis-ui) |
| +------------------+ +------------------+ +----------------------------+ |
| | Components (142+) | | SCSS System | | Icons (105+) | |
| | - Button | | - base/ | | Themes | |
| | - Form/Input... | | - components/ | | Hooks | |
| | - Table | | - helper/ (Tail- | | Utils | |
| | - Menu/Tabs/... | | wind-like CSS) | | | |
| +------------------+ +------------------+ +----------------------------+ |
+=============================+=============================================+
| (依赖)
+=============================v=============================================+
| L2: 核心基础设施层 (amis-core) |
| +---------------------+ +---------------------+ +--------------------+ |
| | Factory System | | Store System (MST) | | Action System | |
| | - registerRenderer | | - RendererStore | | - handleAction() | |
| | - resolveRenderer | | - ServiceStore | | - dispatchEvent() | |
| | - @Renderer decorator| | - FormStore | | - ListenerAction | |
| | - filterSchema | | - CRUDStore | | - ajax/dialog/... | |
| +---------------------+ | - TableStore/2 | +--------------------+ |
| | - ListStore | |
| +---------------------+ | - FormItemStore | +--------------------+ |
| | SchemaRenderer | | - ModalStore | | Theme & Locale | |
| | - 递归解析引擎 | | - PaginationStore | | - themeable HOC | |
| | - 可见性控制 | | - AppStore | | - makeTranslator | |
| | - 变量解析与过滤 | | - ComboStore | | - localeable HOC | |
| | - 全局事件绑定 | | - RootStore | +--------------------+ |
| +---------------------+ +---------------------+ |
| |
| +---------------------+ +---------------------+ +--------------------+ |
| | Utils (75+ files) | | Global Variables | | Scoped Context | |
| | - api.ts | | - globalVar.ts | | - Scoped.tsx | |
| | - dataMapping.ts | | - globalVarClient... | | - filterTarget() | |
| | - tpl.ts (模板引擎) | | | | - IScopedContext | |
| | - helper.ts | | | | - StatusScoped | |
| +---------------------+ +---------------------+ +--------------------+ |
+=============================+=============================================+
| (依赖)
+=============================v=============================================+
| L1: 表达式引擎层 (amis-formula) |
| +------------------+ +------------------+ +----------------------------+ |
| | Lexer (词法分析) | | Parser (语法解析)| | Evaluator (求值器) | |
| | - 词法 token 化 | | - AST 构建 | | - Evaluator (同步) | |
| | - 运算符/变量识别 | | - 运算符优先级 | | - AsyncEvaluator (异步) | |
| | | | - 公式/函数语法 | | - 沙箱安全执行 | |
| +------------------+ +------------------+ | - 上下文注入 | |
| +----------------------------+ |
| +------------------+ +------------------+ +----------------------------+ |
| | Filter System | | Function System | | Doc System | |
| | - registerFilter | | - registerFunc | | - doc.ts (58KB 函数文档) | |
| | - extendsFilters | | - functionDocs | | - doc.md (30KB 文档) | |
| +------------------+ +------------------+ +----------------------------+ |
+=============================================================================+2.3 目录结构
| 标签 | 数量 | 主要分布 |
|---|---|---|
| 【核心基建】 | 主导 | amis-core, amis-formula, amis-editor-core, factory, store, SchemaRenderer 等 |
| 【业务模块】 | 大量 | amis 渲染器, amis-editor 插件, office-viewer |
| 【UI 视图】 | 大量 | amis-ui 组件/样式/图标, scss 系统 |
| 【工具集】 | 较多 | utils/, scripts/, mock/, types/ |
| 【配置】 | 较多 | 根配置文件, docs/, examples/, locale/ |
| 【质量保证】 | 适量 | 各包的 tests/ |
| 【废弃】 | 1 | fis-conf.js (FIS3, 已迁移到 Vite) |
amis/
├── packages/ # 【核心基建】Monorepo 包目录(npm workspaces)
│ │
│ ├── amis-formula/ # 【核心基建】L1: 表达式引擎(词法→语法→求值)
│ │ └── src/
│ │ ├── lexer.ts # 【核心基建】词法分析器:字符串 → Token 流
│ │ ├── parser.ts # 【核心基建】语法解析器:Token 流 → AST
│ │ ├── evalutor.ts # 【核心基建】同步表达式求值器(79KB,核心引擎)
│ │ ├── evalutorForAsync.ts # 【核心基建】异步表达式求值器
│ │ ├── filter.ts # 【核心基建】过滤器注册系统
│ │ ├── function.ts # 【核心基建】公式函数注册系统
│ │ ├── doc.ts # 【核心基建】公式函数文档词典(58KB)
│ │ ├── doc.md # 【配置】公式文档(30KB)
│ │ ├── index.ts # 【核心基建】包入口(导出 evaluate/parse/lexer)
│ │ └── types.ts # 【核心基建】引擎类型定义
│ │
│ ├── amis-core/ # 【核心基建】L2: 核心基础设施层
│ │ └── src/
│ │ ├── index.tsx # 【核心基建】包入口(导出所有核心 API + render 函数)
│ │ ├── factory.tsx # 【核心基建】渲染器工厂(register/resolve/filter)
│ │ ├── SchemaRenderer.tsx # 【核心基建】递归 Schema 解析渲染引擎
│ │ ├── Root.tsx # 【核心基建】根组件(ScopedRootRenderer)
│ │ ├── RootRenderer.tsx # 【核心基建】根渲染器(数据初始化 + 动作处理中枢)
│ │ ├── Scoped.tsx # 【核心基建】数据作用域组件
│ │ ├── WithStore.tsx # 【核心基建】MST Store 注入 HOC
│ │ ├── schema.ts # 【核心基建】JSON Schema 类型定义(33KB)
│ │ ├── types.ts # 【核心基建】核心 TypeScript 类型
│ │ ├── theme.tsx # 【核心基建】主题系统(themeable HOC)
│ │ ├── locale.tsx # 【核心基建】国际化系统
│ │ ├── env.tsx # 【核心基建】RendererEnv 环境定义
│ │ ├── globalVar.ts # 【核心基建】全局变量系统
│ │ ├── store/ # 【核心基建】MST Store 状态管理系统
│ │ │ ├── index.ts # 【核心基建】Store 导出入口
│ │ │ ├── root.ts # 【核心基建】RootStore(页面根 Store)
│ │ │ ├── service.ts # 【核心基建】ServiceStore(API 数据加载)
│ │ │ ├── form.ts # 【核心基建】FormStore(表单状态管理)
│ │ │ ├── formItem.ts # 【核心基建】FormItemStore(表单项状态)
│ │ │ ├── crud.ts # 【核心基建】CRUDStore(列表增删改查)
│ │ │ ├── table.ts # 【核心基建】TableStore(旧版表格)
│ │ │ ├── table2.ts # 【核心基建】TableStore2(新版表格)
│ │ │ ├── list.ts # 【核心基建】ListStore(简单列表)
│ │ │ ├── combo.ts # 【核心基建】ComboStore(组合表单)
│ │ │ ├── modal.ts # 【核心基建】ModalStore(弹窗状态)
│ │ │ ├── pagination.ts # 【核心基建】PaginationStore(分页)
│ │ │ ├── app.ts # 【核心基建】AppStore(应用级状态)
│ │ │ └── manager.ts # 【核心基建】Store 管理器(全局注册表)
│ │ ├── utils/ # 【工具集】核心工具函数库(75+ 文件)
│ │ │ ├── api.ts # 【工具集】API 请求封装 + 适配器
│ │ │ ├── tpl.ts # 【工具集】模板引擎(filter/表达式解析)
│ │ │ ├── helper.ts # 【工具集】通用辅助函数
│ │ │ ├── dataMapping.ts # 【工具集】数据映射转换
│ │ │ ├── formula.ts # 【工具集】表达式工具(桥接 amis-formula)
│ │ │ ├── renderer-event.ts # 【工具集】渲染器事件系统
│ │ │ ├── animation.ts # 【工具集】动画工具
│ │ │ └── ... # 70+ 文件
│ │ ├── actions/ # 【核心基建】动作系统(事件行为定义)
│ │ ├── renderers/ # 【核心基建】基础渲染器(Form/Item/Options/Placeholder)
│ │ ├── components/ # 【核心基建】核心基础组件(LazyComponent/Overlay/ErrorBoundary)
│ │ └── hooks/ # 【核心基建】React Hooks(useEnvContext 等)
│ │
│ ├── amis-ui/ # 【UI 视图】L3: 基础 UI 组件库
│ │ ├── src/
│ │ │ ├── components/ # 【UI 视图】142+ 基础 UI 组件
│ │ │ │ ├── calendar/ # 【UI 视图】日历组件
│ │ │ │ ├── condition-builder/# 【UI 视图】条件构建器
│ │ │ │ ├── formula/ # 【UI 视图】公式编辑器组件
│ │ │ │ ├── json-schema/ # 【UI 视图】JSON Schema 编辑器
│ │ │ │ ├── menu/ # 【UI 视图】菜单组件
│ │ │ │ ├── schema-editor/ # 【UI 视图】Schema 编辑器
│ │ │ │ ├── table/ # 【UI 视图】表格视图组件
│ │ │ │ └── virtual-list/ # 【UI 视图】虚拟列表
│ │ │ ├── hooks/ # 【UI 视图】React Hooks
│ │ │ ├── icons/ # 【UI 视图】图标组件库(105+)
│ │ │ ├── themes/ # 【UI 视图】主题组件(antd/cxd/default)
│ │ │ ├── locale/ # 【配置】国际化语言包
│ │ │ └── utils/ # 【工具集】UI 工具函数
│ │ └── scss/ # 【UI 视图】SCSS 样式系统
│ │ ├── base/ # 【UI 视图】基础样式
│ │ ├── components/ # 【UI 视图】组件样式
│ │ ├── helper/ # 【UI 视图】辅助工具类(类似 Tailwind CSS)
│ │ │ ├── background/ # 【UI 视图】背景工具类
│ │ │ ├── border/ # 【UI 视图】边框工具类
│ │ │ ├── flex/ # 【UI 视图】Flexbox 工具类
│ │ │ ├── grid/ # 【UI 视图】Grid 工具类
│ │ │ ├── spacing/ # 【UI 视图】间距工具类
│ │ │ └── typography/ # 【UI 视图】排版工具类
│ │ ├── layout/ # 【UI 视图】布局样式
│ │ └── themes/ # 【UI 视图】主题样式
│ │
│ ├── amis/ # 【核心基建】L4: 业务渲染层(JSON → 页面)
│ │ ├── src/
│ │ │ ├── index.tsx # 【核心基建】包入口(导出所有业务渲染器 + Schema)
│ │ │ ├── Schema.ts # 【核心基建】主 Schema 类型
│ │ │ ├── SchemaFull.ts # 【核心基建】完整 Schema(27KB,全量类型定义)
│ │ │ ├── SchemaMinimal.ts # 【核心基建】最小 Schema(25KB,精简版)
│ │ │ ├── minimal.ts # 【核心基建】最小化入口注册(23KB)
│ │ │ ├── compat.ts # 【核心基建】向后兼容层(15KB)
│ │ │ ├── schemaExtend.ts # 【核心基建】Schema 扩展工具
│ │ │ ├── preset.tsx # 【核心基建】预设配置
│ │ │ ├── types.ts # 【核心基建】类型导出
│ │ │ └── renderers/ # 【业务模块】业务渲染器
│ │ │ ├── Form/ # 【业务模块】表单渲染器(95+ 表单项)
│ │ │ ├── Table/ # 【业务模块】旧版表格渲染器
│ │ │ ├── Table2/ # 【业务模块】新版表格渲染器
│ │ │ └── icons/ # 【UI 视图】渲染器专用图标
│ │ └── __tests__/ # 【质量保证】主包测试用例(大量快照测试)
│ │
│ ├── amis-editor-core/ # 【核心基建】L5: 可视化编辑器核心基础设施
│ │ └── src/
│ │ ├── index.ts # 【核心基建】包入口
│ │ ├── manager.ts # 【核心基建】插件管理器(68KB,核心)
│ │ ├── plugin.ts # 【核心基建】插件类型定义(40KB)
│ │ ├── inlineEdit.ts # 【核心基建】内联编辑组件(8KB)
│ │ ├── deepSplice.ts # 【核心基建】深层数组操作工具
│ │ ├── util.ts # 【工具集】编辑器工具函数(53KB)
│ │ ├── variable.ts # 【核心基建】变量系统
│ │ ├── component/ # 【核心基建】编辑器基础组件(Panel/base)
│ │ ├── dnd/ # 【核心基建】拖拽系统(Drag & Drop)
│ │ ├── icons/ # 【UI 视图】编辑器图标
│ │ ├── layout/ # 【核心基建】编辑器布局组件
│ │ ├── locale/ # 【配置】编辑器国际化
│ │ ├── plugin/ # 【核心基建】编辑器插件基础框架
│ │ └── store/ # 【核心基建】编辑器 Store 管理
│ │
│ ├── amis-editor/ # 【业务模块】L5: 可视化编辑器 UI
│ │ └── src/
│ │ ├── index.tsx # 【核心基建】包入口
│ │ ├── builder/ # 【核心基建】页面构建器
│ │ ├── component/ # 【核心基建】编辑器主组件
│ │ ├── icons/ # 【UI 视图】编辑器功能图标
│ │ │ ├── btn/ # 【UI 视图】按钮分类图标
│ │ │ ├── form/ # 【UI 视图】表单分类图标
│ │ │ ├── layout/ # 【UI 视图】布局分类图标
│ │ │ ├── display/ # 【UI 视图】展示分类图标
│ │ │ └── ... # 更多分类
│ │ ├── locale/ # 【配置】编辑器语言包
│ │ ├── plugin/ # 【业务模块】86+ 组件编辑插件
│ │ │ ├── CRUD2/ # 【业务模块】CRUD2 组件插件
│ │ │ ├── Form/ # 【业务模块】表单组件插件
│ │ │ ├── Layout/ # 【业务模块】布局组件插件
│ │ │ └── Others/ # 【业务模块】其他组件插件
│ │ ├── renderer/ # 【核心基建】编辑器渲染器控件(45+)
│ │ │ ├── FormulaControl.tsx # 【核心基建】公式编辑器控件
│ │ │ ├── DataBindingControl.tsx # 【核心基建】数据绑定控件
│ │ │ ├── APIControl.tsx # 【核心基建】API 配置控件
│ │ │ ├── ColumnControl.tsx # 【核心基建】列配置控件
│ │ │ └── ... # 40+ 控件
│ │ ├── tpl/ # 【核心基建】编辑器模板系统
│ │ ├── util.ts # 【工具集】编辑器工具函数
│ │ └── validator.tsx # 【核心基建】编辑器校验系统
│ │
│ ├── amis-theme-editor-helper/ # 【工具集】主题编辑器辅助工具
│ │ └── src/
│ │ ├── helper/ # 【工具集】辅助函数
│ │ ├── systemTheme/ # 【工具集】系统主题定义(component.ts 6158行)
│ │ ├── renderers/ # 【工具集】渲染器
│ │ ├── style/ # 【UI 视图】样式
│ │ └── locale/ # 【配置】国际化
│ │
│ ├── office-viewer/ # 【业务模块】Office 文档在线预览
│ │ └── src/
│ │ ├── common/ # 【工具集】通用工具
│ │ ├── excel/ # 【业务模块】Excel 预览引擎
│ │ │ ├── data/ # 【业务模块】数据处理
│ │ │ ├── edit/ # 【业务模块】编辑功能
│ │ │ ├── formula/ # 【业务模块】公式计算
│ │ │ ├── io/excel/ # 【业务模块】Excel 文件读取与渲染
│ │ │ ├── render/ # 【业务模块】渲染引擎
│ │ │ ├── sheet/ # 【业务模块】工作表管理
│ │ │ └── types/ # 【业务模块】Excel 类型定义
│ │ ├── openxml/ # 【核心基建】OpenXML 解析引擎
│ │ │ ├── drawing/ # 【核心基建】图形/绘图解析(presetShape.ts 38,785行)
│ │ │ ├── math/ # 【核心基建】数学公式解析
│ │ │ └── word/ # 【核心基建】Word 文档解析
│ │ ├── word/ # 【业务模块】Word 预览引擎
│ │ │ ├── parse/ # 【业务模块】Word 解析
│ │ │ └── render/ # 【业务模块】Word 渲染
│ │ ├── package/ # 【业务模块】Office 文件解包/打包
│ │ ├── util/ # 【工具集】工具函数
│ │ └── tools/ # 【工具集】辅助工具(XSD 解析等)
│ │
│ └── vite-plugin-amisr/ # 【工具集】Vite 插件
│ └── src/ # 【工具集】JSON → React 组件热重载插件
│
├── docs/ # 【配置】项目文档(中文)
├── examples/ # 【配置】示例代码和演示页面
├── mock/ # 【工具集】Mock 数据(开发调试用)
├── scripts/ # 【工具集】构建、发布与自动化脚本
├── types/ # 【工具集】TypeScript 类型声明补丁
├── reports/ # 【配置】项目分析报告
├── package.json # 【配置】Monorepo 根配置
├── fis-conf.js # 【废弃】FIS3 构建配置(29KB,已被 Vite 替代)
├── vite.config.ts # 【配置】Vite 构建配置
└── README.md # 【配置】项目说明(中文)3. 模块依赖与调用关系
3.1 全局入口与核心路由
- 逻辑说明:用户调用
amis.render(schema, props, options)启动整个渲染流程。入口函数创建 MST Store 实例,初始化环境上下文(env),然后通过 ScopedRootRenderer → RootRenderer 开始递归渲染。在渲染过程中,SchemaRenderer 根据 Schema 中每个节点的type字段,通过渲染器工厂(factory)查找对应的渲染器组件,并递归处理每个节点的body、children、columns等嵌套属性。
调用拓扑 (plainText):
amis.render(schema, props, options) [packages/amis-core/src/index.tsx]
|
+-- AMISSchema (入口组件)
|
+-- RendererStore.create({}, options) [MST Store 初始化]
| |
| +-- getEnv(store) [环境变量注入]
| | +-- fetcher (API 请求)
| | +-- notify (消息通知)
| | +-- jumpTo (页面跳转)
| | +-- isCancel (请求取消)
| |
| +-- envOverwrite(schema, locale, platform) [环境覆盖]
|
+-- ScopedRootRenderer [packages/amis-core/src/Root.tsx]
|
+-- RootRenderer [packages/amis-core/src/RootRenderer.tsx]
|
+-- store.addStore(RootStore) [创建根 Store 节点]
|
+-- render(pathPrefix, schema, props) [核心渲染入口]
|
+-- SchemaRenderer [packages/amis-core/src/SchemaRenderer.tsx]
|
+-- resolveRenderer(path, schema) [渲染器查找]
| |
| +-- renderersTypeMap[type] [按 type 直接匹配]
| +-- renderers[].test(path) [按路径正则匹配]
|
+-- renderer.component (实际组件)
|
+-- [递归处理 body/children/columns 等嵌套属性]
|
+-- 叶子节点 -> amis-ui 基础组件3.2 核心业务实体与关联
- 实体定义:
| 实体 | 描述 | 对应 Store |
|---|---|---|
| Schema (JSON 配置) | 页面的完整 JSON 描述,包含类型、数据、样式、事件等 | 无(纯数据) |
| RendererStore | 全局渲染器 Store,管理所有子 Store | RendererStore |
| RootStore | 页面根 Store,管理页面级数据、路由、弹窗 | RootStore |
| ServiceStore | 服务 Store,管理 API 数据获取与缓存 | ServiceStore |
| FormStore | 表单 Store,管理表单数据、校验、提交 | FormStore |
| CRUDStore | 列表 Store,管理分页列表数据增删改查 | CRUDStore |
| TableStore/TableStore2 | 表格 Store,管理表格数据、列、行操作 | TableStore/TableStore2 |
| FormItemStore | 表单项 Store,管理单个表单项的值、校验 | FormItemStore |
| ListStore | 列表 Store,管理简单列表数据 | ListStore |
| ModalStore | 弹窗 Store,管理全局弹窗状态 | ModalStore |
| ComboStore | 组合 Store,管理多层级嵌套表单组合 | ComboStore |
| PaginationStore | 分页 Store,管理分页状态 | PaginationStore |
| AppStore | 应用 Store,管理应用级设置 | AppStore |
| ActionObject | 动作对象,描述一个操作(ajax、dialog、link、reload 等) | 无(运行时创建) |
- 实体引用拓扑 (plainText):
[RendererStore] 1 ----> N [StoreNode (MST)]
|
+---- 1 ----> 0..1 [RootStore] (页面根节点)
| |
| +---- 1 ----> N [ServiceStore] (API 服务)
| +---- 1 ----> N [CRUDStore] (列表 CRUD)
| +---- 1 ----> N [FormStore] (表单)
| | |
| | +---- 1 ----> N [FormItemStore] (表单项)
| | +---- 1 ----> N [ComboStore] (组合)
| |
| +---- 1 ----> N [TableStore / TableStore2] (表格)
| +---- 1 ----> N [ListStore] (列表)
| +---- 1 ----> 1 [ModalStore] (弹窗)
| +---- 1 ----> 1 [PaginationStore] (分页)
[Schema] (JSON) -----> [SchemaRenderer] (递归解析引擎)
| |
| +----> [Factory] (渲染器注册与查找)
| | |
| | +----> [Renderers] (渲染器注册表)
| | |
| | +---- [amis 业务渲染器]
| | +---- [amis-ui 基础组件]
| | +---- [自定义渲染器]
| |
| +----> [Store System] (数据管理)
| +----> [Action System] (事件处理)
| +----> [Expression Engine] (amis-formula)4. 核心模块详解
模块一:渲染器工厂系统 (Factory System)
模块名称:Renderer Factory — 渲染器注册、查找、异步加载、Schema 过滤的完整管线
设计说明:工厂系统是 amis 的心脏,实现了一个策略模式 + 装饰器模式的组件注册与分发机制。开发者通过
@Renderer(config)装饰器注册渲染器,工厂按权重(weight)排序存储。在渲染时,通过resolveRenderer(path, schema)按 type 或路径正则匹配查找对应渲染器。系统支持同步/异步渲染器加载、Schema 过滤器链、渲染器别名、MST Store 注入和 Scope 隔离。内部结构图 (plainText):
+-----------------------------+
| registerRenderer() | <-- @Renderer 装饰器调用
| - 校验 type/test |
| - 权重排序插入 |
| - 别名注册 |
| - 组件 HOC 包装 |
| +--> HocStoreFactory | <-- 自动注入 MST Store
| +--> Scoped(component) | <-- 隔离数据作用域
+-------------+---------------+
|
v
+-----------------------------+
| renderers[] (注册表) |
| +------------------------+ |
| | weight: 0 (最高优先级) | |
| | weight: 10 | |
| | weight: 100 (最低优先级)| |
| +------------------------+ |
| renderersTypeMap: { |
| "page": RendererConfig, |
| "form": RendererConfig, |
| "crud": RendererConfig, |
| ... |
| } |
+-------------+---------------+
|
v
+-----------------------------+
| resolveRenderer() | <-- SchemaRenderer 调用
| 1. renderersTypeMap[type] | <-- 优先按 type 精确匹配
| 2. cache[path] | <-- 路径匹配缓存
| 3. renderers[].test(path) | <-- 正则/函数匹配
| 4. 返回 RendererConfig |
+-------------+---------------+
|
v
+-----------------------------+
| renderer.component | <-- 已包装好 Store/Scope 的组件
| +------------------------+ |
| | React Component | |
| | + store prop (MST) | |
| | + data prop | |
| | + dispatchEvent() | |
| | + render() recursion | |
| +------------------------+ |
+-----------------------------+模块二:MST Store 状态管理系统
模块名称:MST Store System — 基于 MobX State Tree 的分层状态管理
设计说明:amis 使用 MST 构建了一个树形 Store 系统。每个页面组件对应一个 Store 节点,形成与 UI 组件树一一对应的 Store 树。数据从上往下流动(parentStore → childStore),事件从下往上冒泡(子组件 → 父组件)。Store 系统管理数据加载(ServiceStore)、表单状态(FormStore)、列表操作(CRUDStore)、表格渲染(TableStore)等场景。
内部结构图 (plainText):
+-----------------------------+
| RendererStore (全局) | 1 个 per session
| - fetcher |
| - notify |
| - isCancel |
| - addStore() |
| - removeStore() |
+-------------+---------------+
|
v addStore(RootStore)
+-----------------------------+
| RootStore (根) | 1 个 per page
| - data (页面数据) |
| - context (上下文) |
| - location/params (路由) |
| - globalVars (全局变量) |
| - dialogSchema (弹窗) |
| - drawerSchema (抽屉) |
+-----+--------+------+------+
| | |
v v v
+--------+ +-------+ +--------+
|Service | |Form | |CRUD |
|Store | |Store | |Store |
|(API) | |(表单) | |(列表) |
+--------+ +---+---+ +--------+
| |
v v
+--------+ +--------+
|FormItem| |Combo |
|Store | |Store |
+--------+ +--------+
数据流动规则:
- parentStore.data 自动传递给 childStore (downStream)
- 子组件通过 scope 向上查找数据
- ServiceStore 加载的数据自动合并到父级 Store
- FormStore 的数据变更通过 MST action 保证可追踪模块三:动作与事件系统 (Action System)
模块名称:Action System — 统一的事件处理与动作分派系统
设计说明:amis 定义了一套完整的动作语义(actionType),包括
reload、ajax、dialog、drawer、url、link、email、copy、toast、saveAs等。所有用户交互(按钮点击、表单提交、行操作)都通过dispatchEvent转换为标准化的RendererEvent,事件携带数据和上下文在组件树中传递。RootRenderer 的handleAction方法是所有动作的中央处理枢纽。内部结构图 (plainText):
用户交互 (点击/提交/选择)
|
v
+----------------------------+
| dispatchEvent(e, data) | <-- 每个组件可调用
| 创建 RendererEvent |
+-------------+--------------+
|
v
+----------------------------+
| RootRenderer.handleAction | <-- 中央处理枢纽
| |
| switch(action.actionType) { |
| case 'reload': |
| scoped.reload(target) |
| case 'ajax': |
| store.saveRemote(api) |
| case 'dialog': |
| store.openDialog(...) |
| case 'drawer': |
| store.openDrawer(...) |
| case 'url'/'link': |
| env.jumpTo(url) |
| case 'toast': |
| env.notify(level, msg) |
| case 'copy': |
| env.copy(content) |
| case 'email': |
| window.open(mailto) |
| case 'saveAs': |
| saveAs(api.url) |
| } |
+-----------------------------+模块四:表达式引擎 (amis-formula)
模块名称:Formula Engine — 自研表达式/公式解析与求值引擎
设计说明:amis-formula 实现了一个完整的表达式引擎,包含词法分析器(Lexer)、语法解析器(Parser)、同步求值器(Evaluator)和异步求值器(AsyncEvaluator)。引擎按流程 token 化输入字符串 → 构建 AST → 在沙箱环境中求值,支持 80+ 内置公式函数(数学、字符串、日期、数组等)。核心设计是安全沙箱:禁用 Function constructor 和 eval,通过 AST 解释执行。
内部结构图 (plainText):
输入: "${name} 今年 ${age} 岁,成绩 ${IF(score>60, '及格', '不及格')}"
|
v
+----------------------------+
| Lexer (词法分析器) |
| - 扫描字符流 |
| - 识别 Token: |
| ${ ... } (模板变量) |
| IF(...) (函数调用) |
| > (运算符) |
| name, age, score (变量) |
| '及格' (字符串字面量) |
| - 输出 Token 流 |
+-------------+--------------+
|
v
+----------------------------+
| Parser (语法解析器) |
| - 递归下降解析 |
| - 运算符优先级处理 |
| - 构建 AST: |
| TemplateLiteral |
| +-- Identifier(name) |
| +-- Identifier(age) |
| +-- CallExpression(IF) |
| +-- BinaryOp(>) |
| | +-- score |
| | +-- 60 |
| +-- '及格' |
| +-- '不及格' |
+-------------+--------------+
|
v
+----------------------------+
| Evaluator (求值器) |
| - 遍历 AST 节点 |
| - 从 data 上下文取变量 |
| - 执行函数调用 (沙箱) |
| - 返回求值结果: |
| "张三 今年 18 岁,成绩 及格" |
+----------------------------+模块五:可视化编辑器系统 (Editor System)
模块名称:amis-editor — WYSIWYG 低代码编辑器
设计说明:编辑器分为两层:amis-editor-core 提供编辑器基础设施(插件管理器 PluginManager 68KB、拖拽系统 DnD、内联编辑 InlineEdit、Store),amis-editor 提供可视化编辑功能(86+ 组件插件、属性面板渲染器、页面构建器)。编辑器的工作原理是"操作 Schema → 预览渲染",用户拖拽组件到画布,编辑器修改 JSON Schema,amis 渲染引擎实时呈现结果。
内部结构图 (plainText):
+===========================================================+
| amis-editor (编辑器 UI) |
| +---------------------+ +-----------------------------+ |
| | Component Plugins | | Renderer Controls (45+) | |
| | (86+ 组件编辑插件) | | - FormulaControl | |
| | - Form/ (表单插件) | | - DataBindingControl | |
| | - CRUD2/ (CRUD2) | | - APIControl | |
| | - Layout/ (布局) | | - ColumnControl | |
| | - Others/ (其他) | | - StatusControl | |
| +---------------------+ +-----------------------------+ |
| | Builder | | Validator System | |
| +---------------------+ +-----------------------------+ |
+==========================+=================================+
| (依赖)
+==========================v=================================+
| amis-editor-core (编辑器核心) |
| +-----------------------+ +----------------------------+ |
| | PluginManager (68KB) | | DnD System | |
| | - registerPlugin() | | - Drag & Drop 引擎 | |
| | - resolvePlugin() | | - 排序/移动 | |
| | - plugin lifecycle | +----------------------------+ |
| +-----------------------+ +----------------------------+ |
| | InlineEdit (8KB) | | Editor Store | |
| | - 内联编辑组件 | | - editor state management | |
| +-----------------------+ +----------------------------+ |
+============================================================+
| (依赖)
+==========================v=================================+
| amis (渲染引擎 - 实时预览) |
+============================================================+5. 关键数据流程
场景说明
场景一:用户请求渲染一个页面 — 从
amis.render(schema)调用开始,经过环境初始化、Store 创建、Schema 覆盖、递归渲染,最终返回 React 组件树的完整流程。流转时序图 (Mermaid):
场景说明
场景二:用户交互触发动作 — 从按钮点击、表单提交等用户操作,触发动作(如 reload、ajax、dialog),到最终 UI 更新的完整流程。
流转时序图 (Mermaid):
6. 接口与契约规范
6.1 渲染器注册契约 (TypeScript)
/**
* 渲染器基础配置契约
* 通过 @Renderer(config) 装饰器注册渲染器时的配置接口
*/
export interface RendererBasicConfig {
/** 路径匹配正则表达式(用于识别 Schema type 或路径模式) */
test?: RegExp | TestFunc;
/** 渲染器类型标识(如 'page', 'form', 'crud') */
type?: string;
/** 别名列表,可绑定多个 type */
alias?: Array<string>;
/** 注册名称(用于 debug 和查找) */
name?: string;
/** 关联的 MST Store 类型,如 'FormStore', 'CRUDStore' */
storeType?: string;
/** 是否需要继承上层数据域 */
storeExtendsData?: boolean | ((props: any) => boolean);
/** 权重,值越低越优先命中(默认 0) */
weight?: number;
/** 是否隔离数据作用域 */
isolateScope?: boolean;
/** 是否为表单项 */
isFormItem?: boolean;
/** 是否覆盖已注册的渲染器 */
override?: boolean;
/** 全局变量变化时的回调 */
onGlobalVarChanged?: (instance: React.Component, schema: any, data: any) => void | boolean;
}
/**
* 完整的渲染器配置(含组件引用)
*/
export interface RendererConfig extends RendererBasicConfig {
/** 已包装 Store/Scope 的 React 组件 */
component?: React.ComponentType<RendererProps>;
/** 原始(未包装)的 React 组件 */
Renderer?: React.ComponentType<RendererProps>;
/** 异步加载渲染器的工厂函数 */
getComponent?: () => Promise<{default: React.ComponentType<RendererProps>} | any>;
}
/**
* 渲染器组件接收的 Props 契约
*/
export interface RendererProps extends ThemeProps, LocaleProps, OnEventProps, StatusScopedProps {
/** 递归渲染函数:将子 Schema 渲染为组件 */
render: (region: string, node: SchemaNode, props?: PlainObject) => JSX.Element;
/** 运行环境对象(fetcher, notify, jumpTo 等) */
env: RendererEnv;
/** 当前节点路径(如 'page/body/0/body/0') */
$path: string;
/** 原始 JSON Schema 配置 */
$schema: any;
/** 当前节点的 MST Store 实例 */
store?: IIRendererStore;
/** 当前节点的数据上下文 */
data: { [propName: string]: any };
/** 事件分发函数 */
dispatchEvent: (e: string | React.MouseEvent, data: any, renderer?: React.Component, scoped?: IScopedContext) => Promise<RendererEvent>;
/** 全局事件广播回调 */
onBroadcast?: (type: string, rawEvent: RendererEvent, ctx: any) => any;
/** 是否启用移动端原生 UI 模式 */
mobileUI?: boolean;
}6.2 环境接口契约 (TypeScript)
/**
* amis 运行时环境契约
* 使用方必须实现此接口来集成 amis
*/
export interface RendererEnv {
/** 请求发送器:amis 所有 API 请求通过此方法发送 */
fetcher: (config: FetcherConfig) => Promise<fetcherResult>;
/** WebSocket 数据接收器 */
wsFetcher?: (ws: WsObject, onMessage: (data: any) => void, onError: (error: any) => void) => {close: () => void};
/** 请求是否可以取消(配合 useCancel 使用) */
isCancel: (value: any) => boolean;
/** 消息通知方法 */
notify: (type: 'info' | 'success' | 'error' | 'warning', msg: string, conf?: any) => void;
/** URL 跳转方法(amis 所有页面跳转均通过此方法) */
jumpTo: (to: string, action?: any, ctx?: any) => void;
/** 判断当前路由是否活跃 */
isCurrentUrl?: (to: string) => boolean;
/** URL 更新方法(SPA 模式下的路由更新) */
updateLocation?: (location: any, replace?: boolean) => void;
/** 剪贴板复制方法 */
copy?: (contents: string, options?: any) => void;
/** 用户行为埋点追踪 */
tracker?: (eventTrack: EventTrack, props: any) => void;
/** 主题对象 */
theme?: any;
/** HTML 过滤方法(可用于 XSS 防护) */
filterHtml?: (input: string) => string;
/** 是否为移动端 */
isMobile?: () => boolean;
/** 页面 ID 获取方法 */
getPageId?: () => string;
/** JSON 配置中的文本替换方法 */
replaceText?: {[propName: string]: string};
/** 文本替换时忽略的 key */
replaceTextIgnoreKeys?: Array<string>;
/** 渲染器自定义查找方法 */
rendererResolver?: (path: string, schema: Schema) => null | RendererConfig;
/** 页面 meta 信息更新回调 */
pageMetaEffect?: (meta: AMISPageMeta) => void;
/** URL 解析方法 */
parseLocation?: () => { pathname: string; query: Record<string, string> };
}6.3 MST Store 契约 (TypeScript)
/**
* MST Store 节点基础契约
* 所有 Store 类型都遵循此基础接口
*/
export interface IIRendererStore {
/** Store 唯一 ID */
id: string;
/** Store 类型标识(如 'FormStore', 'CRUDStore') */
storeType: string;
/** 当前节点的路径 */
path: string;
/** 父 Store 的 ID */
parentId: string;
/** 数据域:包含了所有上层 Store 合并后的数据 */
data: Record<string, any>;
/** 下游合并数据(data + 当前层数据) */
downStream: Record<string, any>;
/** 是否有子 Store */
hasChildren: boolean;
/** 上下文数据(在弹窗/抽屉中也能继承) */
context: Record<string, any>;
/** 获取子 Store */
getChildById(id: string): IIRendererStore | null;
/** 获取所有子 Store */
getChildren(): Array<IIRendererStore>;
}
/**
* ServiceStore — API 数据服务契约
*/
export interface IServiceStore extends IStoreNode {
/** 加载状态 */
loading: boolean;
/** 错误信息 */
error?: string;
/** 消息文本 */
msg?: string;
/** 获取 API 配置 */
getApi: (api?: Api, ctx?: any) => ApiObject | undefined;
/** 初始化数据加载 */
initLoading: () => Promise<void>;
/** 发送异步请求 */
fetchData: (api: Api, ctx?: any) => Promise<any>;
/** 重新加载 */
reload: (subpath?: string, ctx?: any) => Promise<void>;
}
/**
* FormStore — 表单状态管理契约
*/
export interface IFormStore extends IStoreNode {
/** 当前表单值 */
values: Record<string, any>;
/** 表单错误信息 */
errors: Record<string, string>;
/** 是否正在提交 */
submitting: boolean;
/** 是否已触摸 */
touched: boolean;
/** 设置表单值 */
setValues: (values: Record<string, any>) => void;
/** 表单提交 */
submit: () => Promise<any>;
/** 表单校验 */
validate: () => Promise<boolean>;
/** 表单重置 */
reset: () => void;
}7. 快速开始
7.1 环境要求
- Node.js 12/14/16/18
- npm 7+(需支持 workspaces)
7.2 安装与运行
# 安装项目依赖
npm i --legacy-peer-deps
# 启动开发服务器
npm start
# 访问 http://127.0.0.1:8888/examples/pages/simple
# 开发编辑器
# 访问 http://127.0.0.1:8888/packages/amis-editor/7.3 测试
# 构建(Jest 不直接支持 TypeScript)
npm run build
# 运行所有测试
npm test --workspaces
# 运行特定测试
npm test --workspace amis -- -t <spec-name>
# 查看覆盖率
npm run coverage
# 更新快照
npm run update-snapshot7.4 典型用例
import { render } from 'amis';
// 定义页面 JSON Schema
const schema = {
type: 'page',
title: '示例页面',
body: {
type: 'form',
api: '/api/submit',
body: [
{ type: 'input-text', name: 'name', label: '姓名' },
{ type: 'input-email', name: 'email', label: '邮箱' }
]
}
};
// 渲染到页面
const element = render(schema, {}, {
fetcher: (config) => fetch(config.url, config).then(r => r.json())
});
ReactDOM.render(element, document.getElementById('root'));