化繁为简,开箱即用 | 阿里经济体Formily开源表单方案建设

简介: Formily谐音family,集标准表单描述Schema协议、表单渲染、表单组件及周边生态一体的统一表单解决方案。

作者:云数

image.png

Formily谐音family,集标准表单描述Schema协议、表单渲染、表单组件及周边生态一体的统一表单解决方案。

背景

纵观近几年前端技术发展方向,以及延伸到未来前端发展方向,我们可以总结为以下几个阶段:F2V(Function函数驱动视图,以jQuery为代表),D2V(Data数据驱动视图,以MVVM框架React、Angular、Vue为代表),C2V(Component组件驱动视图,以Ant Design、Fusion Design为代表),T2V(Template模板驱动视图,以Ant Design Pro等为代表),S2V(Scene场景驱动视图),M2V(Model模型驱动视图)以及 AI2V建设(AI智能驱动视图,比如以ImageCook为典型代表)。各个阶段从下至上环环相扣,紧密依赖,虽然各层在同一时期都有建设,但最终上层建设的完善离不开下层建设的基础。

image.png

在组件化、模板化建设趋于完善的状态下,通过特定场景(例如表单、列表等)进行提效是当下中后台建设的关键,即当前处于S2V场景驱动视图建设的关键时期。能否建立一套标准方案,使协议通、物料通、能力通,是开箱即用SDK战役核心要解决的问题,而在中后台业务中,表单是任何业务都避免不了的一个基本需求。在当前表单方案需求多、效率低、性能差,各BU业务都在重复性建设的背景下,表单核心要实现的目标如下:

  1. 统一集团表单解决方案,具备高可用、高性能、高扩展性等特点,避免重复建设;
  2. 建立一套标准表单Schema描述协议,提升表单开发效率及动态化需求,为未来自动化、智能化提供协议基石;
  3. 统一表单Schema协议渲染引擎,生态表单组件无缝接入,提供自定义组件机制及接入能力;
  4. 不断完善表单开发周边工具生态,降低表单开发门槛,提升表单开发效率。

整体方案基于UForm(现已更名为Formily)为建设蓝本,在协议层进行了标准化约定及扩展、扩展了工具层,渲染层和表单层进行了细节方案设计及代码重构工作。UForm以其分布式状态管理的高性能特点以及在开源社区的良好口碑,为表单共建提供了有利条件。

整个表单方案建设人员包含了阿里经济体绝大部分BU,包括淘系、供应链、数据技术及产品技术部、飞猪、口碑、CBU、ICBU、CCO、CRO、GOC、阿里云、阿里妈妈、优酷大文娱等。这些同学在各BU基本代表了表单方向的核心负责人,在共建方案上把过往的一些宝贵经验分享出来,同时投入到统一方案建设当中,众多人员参与其中,这在其他建设上也是很少见的。

整体架构

基于上述目标,整个表单方案分4层建设,整体架构图如下:

image.png

4层建设分别为协议层、工具层、渲染引擎及表单组件层协议层主要定义了表单的描述协议,有10+协议规范,部分仍在提案中(比如布局方案),完备的描述能力,后面会有详细描述。工具层是指在协议的基础上,提供一个可视化的协议生成工具,具备schema快速生成、可视化配置及实时预览功能,工具层实际是一个react组件,最终会以@formily/react-schema-editor NPM包形式对外提供能力。渲染引擎是基于标准schema协议的渲染实现,所有在协议层定义的能力都将在这一层实现,同时能够对react生态表单输入组件及自定义组件无缝接入,同样以@formily/react-schema-renderer NPM包的形式提供。表单组件层是渲染层实现的核心依赖,表单组件层负责表单消息通信、状态管理及副作用的逻辑处理,这一层对上层业务一般可以不关心,以@formily/core 包向上层输出能力。

适用场景

在业界已有很多表单方案的情况下,什么情况适用Formily表单呢?

  • 表单项不固定,对动态表单渲染有需求;
  • 表单项特别多,对渲染性能有严苛要求;
  • 对现有的表单组件不满意,寻求更好的解决方案。

建设方案

协议层

在表单这一特定场景下,表单描述具备高度可抽象的能力。表单标准描述协议,旨在通过对表单领域描述抽象,提供一份标准描述协议,以满足协议驱动以及动态渲染表单需求,降低表单开发成本,同时为未来自动化、智能化奠定协议基础。表单核心要素包含2部分:数据 + UI,在前期大量实践方案及调研的背景下,通过 JSON Schema 官方标准 + UI Schema描述,实现对表单、表单项、嵌套、循环、校验、联动、异步、组件扩展及布局等能力。

image.png

对于前端同学来说,JSON Schema并不陌生,这里不对JSON Schema做过多介绍,表单协议对于数据描述强依赖JSON Schema。在JSON Schema外,通过x-的扩展方式,抽象了4个属性以对表单UI进行描述,现对这4个属性进行解释。

  • x-props:字段属性描述,通俗可以理解为FormItem属性定义;
  • x-rules: 字段校验描述,Array类型,支持通用的必填、正则校验、函数校验以及错误信息提示;
  • x-component:字段编辑组件类型,比如Input、Select等,另外仍然可以是CustomComponent,通过渲染层注入组件即可;
  • x-component-props:编辑组件属性,这个应该很好理解,不过多解释。

需要说明的一点是,无论是x-props还是x-component-props,我们并不对其内部的属性进行约束,内部属性描述完全取决于组件库或自定义组件的属性,这部分无法枚举,也没法做到统一,因为不纳入协议规范中。

基础协议

基于此协议规范,对于最基本的表单、表单项描述,我们举一个最简单的例子:

{
    "type": "object",
    "title": "表单标题",
    "properties": {
        "name": {
            "type": "string",
            "title": "姓名",
            "default": "淘小宝",
            "x-props" : {
                "extra": "不得超过6个字符",
                "labelCol": {
                    "span": 6
                },
                "wrapperCol": {
                    "span": 18
                }
            },
            "x-component": "Input",
            "x-component-props": {
                "disabled": true,
                "placeholder": "请输入姓名"
            },
            "x-rules": [{
                "required": true
            }]
        }
    }
}

该Schema描述定义了一个简单表单,其中只有一个可以输入姓名的表单项,输入组件为Input,该表单项有一个默认值“淘小宝”...等,其他通过字面都能理解。

表单嵌套、数组定义

表单嵌套、数组定义等都可以基于JSON Schema进行相应的扩展,在Formily整体解决方案中以自定义组件的方式实现,当然官方会提供一套标准嵌套、数组的组件渲染,业务上如果不满足需求,可以进行自定义实现。

联动协议

对于联动协议的描述,在我们的协议制定过程中争论了很长时间,目前达成的一致意见是,通过表达式的方式进行联动描述,表达式以{{}}进行描述,通过渲染层注入root.value(表单值)、root.schema(schema描述)、root.context(上下文)进行解析。

举个例子:

{
    "type": "object",
    "title": "表单标题",
    "properties":{
        "name": {
            "type": "string",
            "title": "姓名",
            "x-component":"Input",
            "x-component-props":{
                "onChange": "{{root.context.fields.setFieldState('age', '')}}"
            }
        },
        "age": {
            "type": "string",
            "title": "年龄",
            "x-component":"NumberPicker",
            "x-component-props":{
                
            }
        }
    }
}

联动表达式中我们通过获取到上下文中的fileds对象,可以设置另外一个字段的任意属性,比如value值、是否禁用/显示隐藏等,实现了联动的处理。这种方式属于主动触发的方式实现,对于一些对性能要求比较高的场景适用。未来希望通过更简单的方式来进行联动描述,即当前字段的值会受什么字段影响,属于被动监听的方式。例如bar字段的值由foo字段决定,是否禁用也由foo字段决定,你可以这样写:

"bar": {
    "type": "string",
    "title": "Bar",
    "x-component":"Input",
    "x-component-props":{
        "value": "{{root.value.foo < 0 ? 'negative' : 'positive'}}",
        "diabled": "{{root.value.foo < 0}}"
    }
}

布局协议

布局协议描述目前仍处于草案阶段,关于布局协议在之前也曾多次讨论到,是否有必要重新定义一套关于布局的协议是比较有争议的点,当然也是我们尽量避免。本身JSON是树形结构,对于描述页面布局具有天然的优势,借助当前的数据描述进行扩展,通过扩展形式标记当前节点代表UI布局,就可以实现对于布局的描述。目前的方案是,沿用当前的协议,通过扩展如 x-skip/x-hide/x-visible以满足对于布局的需求。

举个例子:

image.png

该Schema中定义了一个表单,有姓名和年龄两个表单项,这两个表单项是横向排列,一行两列布局。通过x-skip进行标记,这样在表单进行取值时取到的是{"name":"淘小宝", "age": 18},而不是如下这样的值:

{
    "row" : {
        "col1": {
            "name":"淘小宝",
        },
        "col2": {
            "age": 18
        }
    }
}

工具层

标准Schema协议最终是给机器消费的,对于开发者来说并不友好,因此在标准协议基础上我们实现了Schema生成工具 @formily/react-schema-renderer ,可以非常方便、快速进行Schema配置编辑。Schema生成工具核心能力包含4个:

  • json2Schema快速生成:通过一段数据快速生成最基本的Schema,然后进行属性配置;
  • 可视化配置:内置Antd 和 Fusion两大组件库表单组件属性,输入自动提示;
  • 源码编辑及实时预览:可以对Schema进行源码编辑及渲染表单实时预览;
  • 第三方平台接入:以NPM组件的形式,第三方可以快速进行进入。

image.png
image.png

渲染层

渲染层@formily/react-schema-renderer主要对标准协议规范进行解析,以实现表单渲染。

核心有3个组件:SchemaForm、SchemaField、SchemaMarkup

SchemaForm核心渲染引擎组件,具体功能如下:

  • 标准表单Schema协议解析
  • 表单输入组件注册
  • 初始化设置(value/defaultValue)
  • 事件监听(onSubmit/onChange)
  • 副作用处理(effects)
  • 通信管理(actions)

SchemaField指某一个表单项的实现,等价于标准协议中对每一个字段的描述信息。

SchemaMarkup是指对于布局协议的实现。

限于篇幅,这里不对具体组件实现做过多描述,具体原理可以参考源码。

下面来看一个具体使用的例子:

注:该例子只是用来阐述能力,实际中并不会有两个组件库同时使用的情况。

image.png

例子中实际有两种组件,一种是以value/onChange约定实现组件值输入输出方式,比如Input、Select,另外一种是非value/onChange约定的组件,比如Progress、CheckBox等。按照value/onChange约定在SchemaForm中可以直接注册使用,其他情况则需要进行connect设置valueName的key等。这样实现的好处在于,对于按照约定实现的组件,可以无缝接入(自定义组件也建议实现此约定)。非按照约定实现的组件,仍然可以通过connect的方式注册到表单体系中来。

注:组件注册方式及实现仍在讨论中,近期公布具体方案。

表单组件层

要探究Formily表单组件高性能的原因,需要深入了解Formily在底层的实现。Formily的核心实现在@formily/core这一层,相较于其他表单基于全局状态管理,单项数据流动的理念,Formily在其实现上主要有两点区别:字段状态分布式管理及面向复杂通用组件的通讯管理方案。

image.png

如上图所示,除全局表单状态FormState外,每个字段都维护了一个FieldState,通过内置的路径系统就可以找到对应的字段实例,然后通过setFieldState API更改单个字段状态(具体原理可以参考这篇文章,10分钟解读UForm路径系统)。

我们可以通过2个动图来展示全局状态管理以及分布式状态管理的差异,也就不难理解为什么Formily比其他方案性能更好的原因了。

640.gif
640 (1).gif

总结&未来规划

无论从协议制定,工具层、渲染层及表单组件层建设,项目组成员在各自繁重的业务之余积极加入到共建项目中来,进行协议规范制定、方案讨论及代码开发,在此致敬感谢项目组每个同学的付出。现阶段在协议层、工具层及底层表单组件层基本建设完成。为给用户最好的体验,在渲染组件层仍然有一定的改造工作量,项目组也在积极协调开发中。接下来一段时间重点将在整体链路联调、文档建设以及开源发布上。未来我们将进行Formily在集团内业务的试点落地,同时进行开源运作推广。

官网地址:https://formilyjs.org/
Github开源项目地址:https://github.com/alibaba/formily

在表单使用过程中的任何问题或建议欢迎通过issue联系我们,也可以加我微信(微信号:Andy_Hit)私下交流。

image.png


image.png
关注「Alibaba F2E」
把握阿里巴巴前端新动向

相关文章
|
JSON 前端开发 JavaScript
开源表单方案 Formily 的核心设计思路
Formily 是一个数据+协议驱动的表单解决方案,它站在Reactive响应式编程巨人的肩膀上,构建出了从基础表单到低代码领域的高性能通用基础能力,同时其配套的跨框架+跨终端组件生态体系,也能让用户更高效的开发日常业务表单,尽可能的减少了重复冗余的逻辑实现。本篇内容来自白玄在第十六届D2前端技术论坛的分享,将为你介绍如何在高复杂业务场景下提高我们的表单性能与表单开发效率。
6924 1
开源表单方案 Formily 的核心设计思路
|
API PHP 开发者
大麦网 API 接口商品详情信息 API
为了让更多用户了解到大麦网的商品详情,并能够方便地获取相关信息,大麦网推出了商品详情 API 接口。本文将介绍大麦网商品详情 API 接口的作用、使用方法和注意事项,帮助广大开发者更加方便地接入大麦网的产品。
|
资源调度 前端开发 算法
前端依赖版本重写指南
感谢神奇的 Semver 动态规则,npm 社区经常会发生依赖包更新后引入破坏变更的情况(应用没有使用依赖锁的话),而应用开发者就要在自己的依赖声明里先临时绕过,避免安装到有问题的版本,如果是一级依赖,只需要改 package.json 的声明就可以了,但如果是子依赖,就需要进行版本重写(overrides/resolution)了。本文是一篇针对版本重写功能的指南性文章,当你遇到如下的问题时,就可以按照对应的依赖重写语法,解决这些依赖问题了。
8647 1
前端依赖版本重写指南
|
Java 开发工具 Docker
最全解决docker配置kibana报错 Kibana server is not ready yet
最全解决docker配置kibana报错 Kibana server is not ready yet
2708 0
|
JSON 移动开发 JavaScript
多款顶级好用的 Vue 表单设计器测评推荐,可拖拽生成表单
Vue 前端开发中,表单组件是排在前三的高频使用的组件,如何快速构建表单,节省力气,避免重复造轮子呢,选择一款适合自己的前端表单设计器就非常重要了。本文介绍 4 款顶级好用的 Vue 表单设计器,其中最后一款卡拉云,是新一代低代码开发工具,不仅能自动生成各类表单,还可以拖拽生成其他常见的前端组件,一行代码连接前后端数据,可快速接入数据库/api。它是表单设计器的超集,可直接生成属于你的后台管理工具,无敌好用。
4585 0
多款顶级好用的 Vue 表单设计器测评推荐,可拖拽生成表单
|
5月前
|
存储 人工智能 安全
推荐一款可以简单快速部署开源AI模型的桌面软件 Doo AI
Doo AI是一款简洁易用的开源AI模型本地部署工具,支持通义千问3/VL、LLaMA3.1等主流HF格式模型。下载即用,扫描→点击“加载”,可以快速、轻松完成部署;纯本地运行,隐私安全;支持文本对话、图像识别、RAG、角色提示词等实用功能。(239字)
1706 4
推荐一款可以简单快速部署开源AI模型的桌面软件 Doo AI
|
11月前
|
JSON 前端开发 JavaScript
惊艳!阿里开源 15.2k Star 企业级低代码引擎揭秘,如何变革前端开发方式?
阿里巴巴开源的 LowCodeEngine 是一款企业级低代码引擎,具备可视化编排、UI 渲染、代码生成等全链路能力。支持 React、Vue、Rax 等框架,提供高扩展性与类型安全,助力高效开发,降低维护成本,适用于后台系统、多端同步等场景。
1667 1
|
10月前
|
JSON 监控 前端开发
AMIS:百度开源的前端低代码神器,18.4k star 背后的开发效率提升利器
AMIS(前端低代码框架)是百度开源的低代码前端框架,基于纯 JSON 配置即可生成完整后台页面,包括表单、表格、图表、CRUD 列表,支持可视化拖拽编辑。,星标数已达 18.4k,百度内部已沉淀超过 5 万个页面,广泛应用于审核系统、数据管理后台、模型监控等落地场景
1737 0
|
人工智能 JavaScript Devops
云效 MCP Server:AI 驱动的研发协作新范式
云效MCP Server是阿里云云效平台推出的模型上下文协议(Model Context Protocol)标准化接口系统,作为AI助手与DevOps平台的核心桥梁。通过该协议,AI大模型可无缝集成云效DevOps平台,直接访问和操作包括项目管理、代码仓库、工作项等关键研发资产,实现智能化全生命周期管理。其功能涵盖代码仓库管理、代码评审、项目管理和组织管理等多个方面,支持如创建分支、合并请求、查询工作项等具体操作。用户可通过通义灵码内置的MCP市场安装云效MCP服务,并配置个人访问令牌完成集成。实际场景中,AI助手可自动分析需求、生成代码、创建功能分支并提交合并请求,极大提升研发效率。