Form 表单状态管理工具调研

1,388 阅读6分钟

背景

笔者之前为了为日常开发提效,做了低代码相关的调研,并输出了【低代码漫谈】系列。最大的收获就是从 amis 和 lowcode-engine 偷师,尤其是后者,让笔者对「协议先行」有了更深入的认识。只要协议统一了,就可以屏蔽掉底层框架、组件库甚至是编程语言的差异,更方便开发一些工具来提效。

但是,虽然 lowcode-engine 已经输出了一套很全面的协议,但是还没有完全成熟,比如对于 Vue 系的支持还不够友好(详见《lowcode-engine - Vue Renderer 尝试》)。而笔者的诉求是可以适配 React、Vue2、Vue3 的项目,所以暂时还无法较低成本的享受现有工具的成果。

不过协议先行的思想给了笔者很大的启发,最近也一直在思考这件事情。笔者最开始的诉求是提高表单和列表的开发效率(因为主要是中后台项目),无法统一全部的协议,但是至少可以先统一组件层面的协议吧。说得再具体点就是输出一套统一的表单和列表组件的 API,然后各 UI 组件库按照该协议实现组件。当 API 协议统一后,结合配置化开发可以从多方面提高研发效率。

配置化开发

所谓配置化开发,即将所有的 props 提取成对象,然后把这个对象传给封装好的组件即可,如下伪代码

// config
const formProps = {
  onSubmit() {},
  items: [{
    label: "Name",
    componentName: "Input",
    bind: state.name
  }, {
    label: "Age",
    componentName: "InputNumber",
    bind: state.age
  }],
  // other code
};

// jsx usage
return <FormRender {...formProps} />

// Vue Template usage
<template>
  <FormRender v-bind="formProps" />
</template>

这样做可以带来以下好处:

  1. 使用层面几乎完全统一。不管项目用的是什么框架,什么 UI 组件库,配置代码是完全相同的。这点尤其有利于紧急项目,需要人力临时支援的情况,可以最大限度的降低切换成本;
  2. 业务逻辑与组件完全解耦。这样就可以把配置(本质是业务逻辑)交给新手来写,组件封装交给老手来写。一是不同梯度人才的有效利用。二是可以让组件开发更聚焦,质量更好,也可以最大程度的实现组件复用。这两者相当于变相提高了团队的效率;
  3. 方便辅助工具的开发。因为配置是语言无关的,所以可以很方便的开发一些提效工具,包括但不限于代码片段、VS Code 插件、脚本、甚至可以直接利用现有低代码工具;
  4. 有利于项目的技术迭代。这属于第 2 点的延伸,由于项目当中绝大多数都是业务逻辑,当其与组件解耦时,这就意味着替换组件、组件升级甚至是整个项目技术升级的范围也就缩小了,而且更纯粹了。如果是升级一个 Input 组件,也许只是分分钟的事;

凡事都是两面的,所以配置化也会存在一些风险:

  1. 协议是否合理。合理具有几层含义,一是能够覆盖所有场景,一定要保留自定义能力。二是易用性要好,心智负担不能太重。三是学习成本不能太高,最好与业内应用比较广泛的协议尽量贴近。说实话,这很有难度,很考验设计者的水平;
  2. 如何顺利落地。我们的根本目标是提效,协议制定之后,还要封装组件,小范围实验调试,组织大范围推广、学习,修改现有项目代码,建立组件共享机制等一串连锁的事情要推进和设计。这其中只要有一个环节没有做好,那大概率会出现不上不下很尴尬的局面。甚至如果新老代码混掺,那真不好说是否能够提效;

不管怎样,理论上这个思路还是可以提高研发效率的,而且如果这个思路跑通了,后续还可以进行列表组件、Layout 组件、路由组件、上下文组件等的配置化改造,终极目标就是整个项目的绝大多数逻辑都可以通过配置化实现,那么就真的离低代码只有一线之隔了。先不扩展太多,还是先解决 Form 组件的协议问题吧。

分析调研

状态管理是表单组件最核心最复杂的部分,formilyjs 的文档列出了市面上主流的几个表单状态管理库,我们来比较一下(数据截止至 2022.05.24):

formikreact-hook-formredux-formreact-jsonschema-formformilyreact-final-form
介绍Build forms in React, without the tears !
formik.org
React Hooks for form state management and validation (Web + React Native)
react-hook-form.com
A Higher Order Component using react-redux to keep form state in a Redux store
redux-form.com
A React component for building Web forms from JSON Schema.
rjsf-team.github.io/react-jsons…
Alibaba Group Unified Form Solution -- Support React/ReactNative/Vue2/Vue3
formilyjs.org/
High performance subscription-based form state management for React
final-form.org/react
GitHub30.4k stars
242 watching
2.5k forks
28.3k stars
172 watching
1.4k forks
12.6k stars
176 watching
1.7k forks
11.5k stars
169 watching
1.9k forks
7.7k stars
145 watching
1.1k forks
6.9k stars
84 watching
471 forks
NpmWeekly Downloads
1,999,893
Unpacked Size
580 kB
Last publish
a year ago
Weekly Downloads
2,028,913
Unpacked Size
783 kB
Last publish
3 days ago
Weekly Downloads
391,870
Unpacked Size
1.45 MB
Last publish
6 months ago
Weekly Downloads
154,810
Unpacked Size
3.46 MB
Last publish
18 days ago
Weekly Downloads
5,668
Unpacked Size
1.49 MB
Last publish
13 days ago
Weekly Downloads
464,430
Unpacked Size
191 kB
Last publish
a month ago
备注Npm 数据为:
@rjsf/core
Npm 数据为:
@formily/core
Npm 数据为:
final-form

Star History Chart

image.png

优先参考下载量来看,毫无疑问 formikreact-hook-form 是妥妥的第一梯队,优势非常明显,下载数高了一个数量级。而且后者不管是 stars 还是下载数增加的都很迅速,相信超过 formik 只是时间问题。

处于第二梯队的是 final-formredux-form,前者由于是 react-final-form 的底层,虽然 stars 不是很高,但是下载量着实是不少,而且是纯 js 实现的,框架无关。至于后者,formik 文档开篇就聊了其局限性。所以如果深入研究的话,final-form 由于其框架无关性还具有一定的研究意义,后者暂时就不投入精力深入研究了。

处于第三梯队的是 rjsfformily,其实二者已经不单纯是表单状态管理工具了,同时集成了 UI 方面的逻辑在,算是一套完整的表单配置化解决方案。也正因如此,相较前几个框架,它们的适用范围更窄,数据低一些也就不奇怪了。由于笔者目前是沿着【低代码漫谈】中的思路来研究的,所以二者自带的 UI 解决方案与笔者目前的方案存在些许冲突,所以暂时放弃对二者的深入调研。

总结

  • formik 作为「老牌强者」必然要进行一番深入研究;
  • react-hook-form 作为「新晋黑马」也肯定有其研究的价值;
  • final-form 由于其框架无关性,也有研究一下的必要。

所以笔者后续会对三者进行更深一步的研究,而且会结合低代码的思路,从特殊的角度去分析,敬请期待。

“完美不在于无以复加,而在于无可删减,万事莫不如此。”

"Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away."——Antoine de Saint-Exupery