开源表单方案 Formily 的核心设计思路

简介: Formily 是一个数据+协议驱动的表单解决方案,它站在Reactive响应式编程巨人的肩膀上,构建出了从基础表单到低代码领域的高性能通用基础能力,同时其配套的跨框架+跨终端组件生态体系,也能让用户更高效的开发日常业务表单,尽可能的减少了重复冗余的逻辑实现。本篇内容来自白玄在第十六届D2前端技术论坛的分享,将为你介绍如何在高复杂业务场景下提高我们的表单性能与表单开发效率。


图片.png

Formily 是一个数据+协议驱动的表单解决方案,它站在Reactive响应式编程巨人的肩膀上,构建出了从基础表单到低代码领域的高性能通用基础能力,同时其配套的跨框架+跨终端组件生态体系,也能让用户更高效的开发日常业务表单,尽可能的减少了重复冗余的逻辑实现。本篇内容来自白玄在第十六届D2前端技术论坛的分享,将为你介绍如何在高复杂业务场景下提高我们的表单性能与表单开发效率。

附:第十六届D2前端技术论坛现场分享视频

图片.png


什么是 Formily?


Formily是一款面向中后台复杂场景的数据+协议驱动的表单框架,它也是阿里巴巴集团的统一表单解决方案。借助Formily可以完成复杂的表单页面需求,同时Formily提供的表单设计器可以快速搭建表单。

Formily官网:https://formilyjs.org


1、核心特点:

  • 高性能:Formily在字段数量无限多和高频输入场景下,可以保证O(1)时间复杂度;
  • 框架无关:Formily已经完美兼容React、Reactive、Vue框架;
  • 生态完备:Formily在组件桥接层支持Ant Design、Element、阿里巴巴Fusion组件库;
  • 协议驱动:协助Formily让后端通过JSON动态驱动表单渲染以实现表单可搭建可配置;
  • 相当完备:Formily可以支持各种复杂的表单页面需求。


2、设计原则

  • 单一职责;
  • 优雅命名:遵循简单、直观、一致的标准。


3、核心架构

Formily核心架构分为四层,自下而上分别是:

  • 内核和协议层:
    内核是表单相关UI无关的领域模型系统;
    协议层是基于JSON Schema扩展的表单协议;
  • UI桥接层:基于Formily内核与各种UI框架(如React、Vue)桥接胶水层;
  • 组件扩展层:建立在UI桥接层与UI组件库的桥接胶水层;
  • 应用层:借助Formily可以构建纯源码、低代码、无代码等应用解决方案;
  • Formily开发工具(下图右侧)

图片.pngimage.gif

Formily核心架构


设计思路


1、高性能思路

问题:普通React用法,想要实现数据收集和同步,需要强依赖虚拟DOM的整树重绘才能达到目的。

目标:不管字段数量多少,高频输入永远都是O(1)复杂度。

方案一、ReactFinalForm/Antd4.0方案

抽象FormState/FieldState,内部使用pub/sub模式进行通讯,脏检查控制联动时的渲染重绘。

时间复杂度:

输入时:Ant Design O(1)/ReactFinalForm O(1)

联动时:Ant Design O(1 or n)/ReactFinalForm O(1 or n)

优点:简单,易上手;

问题:脏检查成本高,外部联动无法做到O(1);

图片.png

方案二、UForm/Formily1.x方案

抽象FormState/FieldState,内部使用pub/sub模式通讯,抽象主动更新模型,可以解决方案一中外部联动无法做到O(1)的问题。

时间复杂度

输入时:O(1)

联动时:O(1)

优点:高性能;

问题:学习成本高,外部联动需要转换成主动模型;

图片.png

方案三、ReactHookForm方案

基于DOM机制收集数据,绕过React受控更新机制,保证高频输入无卡顿。

时间复杂度:

输入时:O(1)

联动时:O(n)

优点:足够轻量,简单;

问题:一旦涉及数据联动,还是需要重绘整树;

image.gif图片.png

方案四、Formily2.0方案

依托Reactive响应式解决方案,构建整个响应式表单领域模型。当组件所依赖的响应式变量发生任何变化,组件都会重新渲染,从而解决组件的脏检查问题。

时间复杂度:

输入时:O(1)

联动时:O(1)

优点:

  • 不再需要大量脏检查成本,一切都是基于数据变化精确渲染;
  • 既支持主动更新模型,也支持被动响应模型,在多对一被动联动场景,代码量大大减少;
  • 外部数据与表单内部字段联动时,只需要定义ApplicationReactiveData即可,代码编写成本很低;

问题:学习成本高。

image.gif图片.png

演示:高频输入性能和外部联动

时间复杂度 O(1) 复杂度,2000个字段,针对单个字段的高频输入,完全无卡顿。

image.gif图片.png

高频输入性能演示

image.gif图片.png

外部联动演示


2、协议驱动思路

问题:如何更高效的开发表单?

目标:定义一套通用协议,简单高效的描述表单UI/逻辑,并对低代码搭建友好。

方案一 纯UITree协议方案,类似于JSON版的JSX

优点

  • 足够简单,componentName/props/children完全可以把整个UI结构给描述清楚;
  • 对搭建非常友好;

问题:

只能描述视图结构,无法描述状态模型。

image.gif图片.png

方案二 标准JSON Schema方案,参考ReactJSONSchemaForm

优点:

以数据描述视角来驱动UI渲染,基于这样的数据描述,可以将很多状态处理逻辑固化到渲染引擎或者组件内部,从而使得协议层变得非常干净;

问题:

无法解决UI容器包裹问题,对搭建友好。

image.gif图片.png

方案三 Formily2.0方案,针对JSONSchema的扩展协议
核心思路

• 扩展Void类型描述数据无关布局容器或控件;

• 扩展 x- 属性描述UI控件与控件属性;

优点:

• 完全表达UI,无需第二套协议,学习成本很低;

• 可以将临时状态封装在渲染引擎或者组件内部;

• 对搭建更加友好,因为它已经可以把UI层级给表达出来了;

image.gif图片.png


3、扩展组件思路

问题:如何开发协议思路的自定义组件?

目标:足够简单,符合标准组件开发最佳实践。

  • 基础扩展方案


属性约定,比如value/onChange组件属性约定,保证所有输入型组件可以快速接入。

优点:

符合统一React属性命名规范标准,对于第三方组件接入成本很低;

缺点:

只能约定标准属性,value/onChange/disabled/readOnly之类的,无法约定渲染引擎内部与扩展组件间其他数据交互。

image.gif图片.png


  • 白盒进阶扩展方案


标准Hooks方案,借助ReactContext,就近寻找渲染引擎内部状态模型。

优点:

完全隔离了渲染引擎与组件自身属性,做到了类型更友好,写法更自然的通信模式;

缺点:

对接三方组件每次都需要单独写一个包装组件,不方便快速桥接。

image.gif图片.png


  • 黑盒进阶扩展方案


连接器扩展,与白盒进阶扩展不同的是黑盒用connect和mapProps做了一层包装。

优点:

• 无需重新封装组件,只需要关注属性与字段模型的映射;

• 映射转换逻辑方便复用;

缺点:

学习理解成本高。

image.gif图片.png

  • 高级场景化扩展方案

渲染权限转移模板化方案。Formily提供RecursionField组件负责动态渲染子树。

优点:

可以封装出大量模板组件,模板组件内部可以将布局、交互、逻辑全部固化,在实际使用过程中提效显著,比如ArrayTable/ArrayCard这种自增组件;

缺点

学习理解成本高。

image.gif图片.png

综上所述,Formily的扩展能力是建立在标准组件开发最佳实践基础之上,是没有任何黑魔法的。


使用数据



1、使用数据情况

如下图所示,Formily被广泛应用于阿里系和非阿里系的各种BU的不同场景。

图片.png


2、社区运营数据

图片.png


未来规划


1、规划

  • 进一步优化性能;
  • 构建更多的扩展生态;
  • 支持React18;
  • 思考如何借助Formily一次性解决CRUD页面;


2、不足

• 不兼容IE,且无法解决;

• 整体体积较大,压缩前130k左右,压缩后80k左右,包含桥接组件库;

• 学习成本比较高,计划逐步完善视频教程。


小结:Formily 的价值


Formily在高性能的加持下,实现一套底层适配多个框架,一份Schema适配多端(PC、手机),一个生态覆盖全场景(Pro/Low/No Code)。

相关文章
|
2月前
|
存储 前端开发 JavaScript
高效组件的设计与封装之道
本文结合了作者自身碰到的场景来说明如何做好组件设计和封装。
|
6月前
|
算法 测试技术 数据处理
【C++ 设计思路】优化C++项目:高效解耦库接口的实战指南
【C++ 设计思路】优化C++项目:高效解耦库接口的实战指南
181 5
|
6月前
|
安全
什么是短剧系统开发/需求设计/逻辑方案/项目指南
The short drama system development plan refers to the development of a system for organizing and managing the process of short drama production, release, and playback.
|
6月前
|
存储 监控 安全
插件机制详解:原理、设计与最佳实践
插件机制详解:原理、设计与最佳实践
345 0
|
数据库
易搭工作流引擎用是什么开源 还是阿里自研产品,零代码平台场景页面映射数据库表是动态创建,采用什么框架处理,怎么让系统产生高并发能力。易搭权限有没有了解,求解。
易搭工作流引擎用是什么开源 还是阿里自研产品,零代码平台场景页面映射数据库表是动态创建,采用什么框架处理,怎么让系统产生高并发能力。易搭权限有没有了解,求解。
|
存储 安全 区块链
区块链游戏系统开发(开发详细)/案例开发/设计功能/逻辑方案/源码平台
  区块链游戏系统开发是一个复杂而精密的过程。首先,需要进行需求分析和规划,确定游戏系统的功能和特性。然后,进行技术选型和架构设计,选择适合的区块链平台和开发工具。接下来,进行系统的搭建和编码,实现游戏逻辑和用户交互功能。最后,进行测试和优化,确保系统的稳定性和性能。
|
小程序 前端开发 Java
【平台开发】技术整合思考(四)前后端不分离
【平台开发】技术整合思考(四)前后端不分离
222 0
|
数据可视化 前端开发 Java
云巧组件如何实现代码架构设计可视化
在项目搭建完成进行了N个迭代之后,往往因为需求的变化以及设计的缺陷导致领域模型、接口、数据库设计等和最开始的时候大为不同,架构设计需要保鲜会花去大量的时间。有没有一种办法可以实时反应项目的各种技术设计呢?就像Swagger一样,代码自动生成文档。我们采用了静态代码扫描的方案,通过代码来反应真实的技术设计,这就是《云巧工坊-应用素描》的功能。
276 0
|
前端开发 数据库 数据安全/隐私保护
【平台开发】— 5.后端:代码分层
【平台开发】— 5.后端:代码分层
【平台开发】— 5.后端:代码分层
|
JSON 运维 前端开发
开发中遇到的问题&解决方案(十一)
前天不是开工嘛,然后刚刚到公司前端说测试环境好像挂了,开工就直接王炸了,找了运维,运维说服务器过年关机了回来发现有个配件坏了,暂时修不好。那我就本地部署一套当测试环境用,我同步了一份生产库到本地,然后问题就来了,之前好好的功能全部出现了问题,因为年前有需求改动,debug了好几遍代码也没有查出问题,然后突然想到MySQL版本不对。
144 0
开发中遇到的问题&解决方案(十一)