一、简介
DripForm 是由京东零售 iPaaS 团队开源的 React 表单组件,支持按标准化协议配置或可视化生成表单,并根据不同的 UI 库进行扩展,可灵活高效解决各类复杂表单场景。
二、背景
表单是 CMS 等 B 端业务中出现频率最高的场景,其业务复杂度往往也非常高,不仅要考虑样式布局、数据校验及提交,还需要实现异步逻辑、嵌套联动等功能。同时 B 端业务的生命周期普遍较长,意味着在实际开发时,若一开始没做好规划,代码只会充斥更多的 if else
或 switch case
等逻辑,最终导致系统维护成本大幅上涨。
另外,在前端层面外,表单还存在前后端校验能力无法协同等情况。经常发生前后端的校验规则不一致,或是一端漏校验的情况,并且维护两份代码也带来了更高的成本。
因此,我们设计并开源了动态表单配置方案 DripForm 去解决以上问题,提升表单的开发效率。
三、 亮点与差异
相对业内其他方案,DripForm 具备以下亮点:
- 语义化、标准化:简洁高效的 JSON 协议有助于开发者理解。
- 校验一体化:依托于 ajv 的标准化校验能力,可实现前后端校验一体化。
- 可视化:可视化搭建表单及修改表单 Schema 。
- 可扩展:支持二次开发,可扩展自定义组件集、校验集。 基于标准化协议可实现的前后端校验一体化、可扩展能力等都是 DripForm 与其他方案最大的差异,同时可视化和自动化也能进一步减少协议的学习及配置成本。
四、 如何使用
DripForm 可以独立作为 npm 模块使用,也可搭配可视化生成器通过拖拽生成 Schema 。
npm install @jdfed/drip-form @jdfed/drip-form-theme-xxx
注意:xxx为主题库的名字。
简单使用
import React, { memo } from 'react'
// 引入核心包和主题
import DripForm from '@jdfed/drip-form'
import dripTheme from '@jdfed/drip-form-theme-xxx'
import '@jdfed/drip-form-theme/dist/index.css'
// 引入配置项
import unitedSchema from './unitedSchema.json'
const Form = memo(() => {
return
<DripForm
unitedSchema={unitedSchema}
uiComponents={{'drip': dripTheme}}
/>
})
除了以上面向编程开发的方式,DripForm 结合 DripDesign 、DripTable 等模块,并配合 iPaaS 内 FaaS 能力,提供了一个可以低代码快速搭建 CMS 的平台 DripWorks 。以上的这些模块、平台也会在后续逐步开源或对外提供体验。
五、 架构设计
DripForm 架构设计的目标是降低团队表单开发的维护成本,以易于使用、灵活扩展的方式解决表单开发中常见的联动、校验、异步获取数据、自定义表单等复杂场景。
1. 功能梳理及设计
核心功能包括 UI、校验、联动,通过 JSON Schema 协议进行配置。除此之外还需具备扩展、可视化等功能。
- UI:表单的展示与行为。需满足不同业务对不同UI库的诉求,考虑到目前主流ui库都很成熟稳定,因此 DripForm 架构上 UI 库解耦,可通过主题应用不同的 UI库。
- 校验:复杂表单值的校验。使用 JSON Schema 规范数据校验,配合 ajv 实现前后端校验统一。
- 联动:表单项变化后,不同表单间的联动关系,采取事件广播等方式实现。
- 扩展性:通用控件及校验无法满足全部业务诉求,因此 DripForm 还支持自定义组件集、校验集。
- 可视化:JSON 配置复杂起来不比写代码简单,因此配套提供可视化生成器,以低代码方式进一步提高表单效率,也可作为 npm 独立使用。
2. 主要模块
上述功能,DripForm 主要通过标准化的协议,搭配表单核心、主题、行为校验等模块实现,并额外提供了表单可视化生成器( generator
)。
1) 协议规范
DripForm 的协议分内外两部分,对开发者提供精简的 unitedSchema
,内部又分为配置校验的 dataSchema
(即 JSON Schema 规范)、配置 UI 的 uiSchema
两种。
DripForm是如何设计,并把dataSchema
、 uiSchema
演进到 unitedSchema
的?可以通过下面这个案例来说明,假设有一份表单数据如下:
{
name:'张三',
age: 18
}
1、输出对应的 dataSchema
协议:
{
"type": "object",
"properties":{
"name":{
"title":"姓名",
"type":"string"
},
"age":{
"title":"年龄",
"type":"number"
}
}
}
2、添加校验,例如对姓名有必填要求、最小最大限制,可以按 JSON Schema 规范添加相应关键字,并根据 ajv-errorMessage
添加错误信息。
{
"type": "object",
"required":["name"],
"errorMessage":{
"required":{
"name":"必填"
}
},
"properties":{
"name":{
"title":"姓名",
"type":"string",
"minLength":2,
"maxLength":4,
"errorMessage":{
"minLength":"最小输入2",
"maxLength":"最大输入4"
}
},
"age":{
"title":"年龄",
"type":"number",
}
}
}
3、增加 UI 描述信息,修改如下:
{
"type": "object",
"schema": [
{
"title": "姓名",
"type": "string",
"minLength": 2,
"maxLength": 4,
"requiredMsg": "必填",
"errorMessage": {
"minLength": "最小输入2",
"maxLength": "最大输入4"
},
"ui": {
"type": "text"
},
"fieldKey": "name"
},
{
"title": "年龄",
"type": "number",
"ui": {
"type": "number"
},
"fieldKey": "age"
}
]
}
考虑到开发者配置的简便性,需要对协议进行一些优化,例如:
-
properties
关键字无法满足表单的有序性要求,因此使用schema
关键字替代properties
关键字;使用fieldKey
代替properties
中的属性。 -
添加
ui
关键字,ui
是一个对象,用于描述表单控件,其余字段透传主题对应 UI 框架的组件 props 字段。{ //表单控件类型 type:string, //表单标题样式 title?:TitleStyle, //表单提示样式 description?:Description, //表单是否展示 vcontrol?:string|VcontrolFunc, //表单数据变化触发函数体 onchange?:string|CustomFunc, //表单主题 theme?:string, [propName:string]:unknown }
-
由于 JSONSchema 规范中,设置必填和错误文案必须在父级,这无疑增加设置成本。因此 untiedSchema 使用
requiredMsg
代替必填和必填错误文案。 -
增加表单的全局配置,比如布局
containerStyle
、主题theme
、校验时机validateTime
。
4、最终输出 unitedSchema 如下:
{
"validateTime": "change",
"type": "object",
"theme": "drip-design",
"schema": [
{
"title": "名字",
"type": "string",
"minLength": 2,
"maxLength": 4,
"errMsg": {
"minLength": "最小输入2位",
"maxLength": "最大输入4位",
"_": "错误兜底文案"
},
"ui": {
"type": "text",
"placeholder": "请输入姓名",
"description": {
"type": "icon",
"title": "hover触发提示",
"trigger": "hover"
}
},
"requiredMsg": "必填",
"fieldKey": "name"
}
]
}
上述配置会生成下面表单:
2) 核心
DripForm 的核心模块,用于加载主题包、加载校验插件、全局状态管理、解析协议等。
3) 全局状态管理
DripForm 没有额外引入状态管理库,使用 hooks+immer+memo 等方式管理数据,在顶级组件中通过 useImperativeHandle
提升表单内部所有数据。表单外部可以通过 ref
对象获取到当前表单数据、校验状态、UI 逻辑、校验逻辑、set
、get
、merge
等。
4) 主题
DripForm 可以通过配置 theme
、uiComponents
来决定使用的主题,可以单一主题,也可以混合使用主题,开源版本中内置了对主流 UI库 如 antd 的适配,方便大家把 DripForm 无缝接入系统中。
theme
关键字可以在全局配置,也可以在某一个表单的 schema 中配置,表单配置优先级高于全局配置。
5) 校验
校验部分使用 JSON Schema、ajv 实现,前后端开发者可基于 ajv 规范对表单 JSON 进行一致化的校验。默认内置 ajv-errors
、ajv-formats
、ajv-keywords
、@jdfed/drip-form-plugin-formats
、@jdfed/drip-form-plugin-keywords
等插件,满足常见场景,也可以自行扩展自定义规则的校验插件,补充关键词或更多功能。
6) 可视化生成器
可视化生成器提供 npm 包形式,支持扩展自定义业务组件。表单配置生成分为左侧组件选择、中间视图拖拽区域、右侧配置区域,生成器本身也是由DripForm所生成的。
新增业务组件或者配置已有的组件只需要配置一份 Schema 即可。
DripFormGenerator使用案例
六、 结尾
除持续迭代优化外,DripForm 近期重心会在提供更多开放API、依据数据自动生成表单等方面,并希望能通过开源,与社区一起交流改进。
你的Star是我们最大的动力,如果对项目有兴趣、有建议,欢迎随时与我们交流~
- 文档: jdfed.github.io/drip-form/d…
- 仓库: github.com/JDFED/drip-…
- 表格: github.com/JDFED/drip-…
- 更多iPaaS前端团队开源能力:Leo脚手架, MicroApp微前端, 水滴表格