jq动态渲染后获取不到元素高度_基于 Ant Design 进行表单配置渲染

77c9b50b309de10fd7bc2a66c67b354c.png

基于 Ant Design 开发了一个表单配置渲染库,可以帮助你通过配置数据快速渲染一个表单并进行表单操作。

Github:https://github.com/beyondxgb/afms

Examples: https://beyondxgb.github.io/afms

  • ✔︎开箱即用,基于最受欢迎的 React 组件库 Ant Design,非常容易上手。
  • ✔︎数据驱动,对表单的任何操作都可以通过操作配置数据完成。
  • ✔︎高维护性,维护表单,只需要维护配置数据。
  • ✔︎高扩展性,可以高度定制自己的表单组件和组装表单组件,轻松应付各种定制需求。
  • ✔︎状态切换,轻松切换表单组件状态(编辑态、展示态、禁用态)。
  • ✔︎复杂布局,具有灵活的布局,可应对各种复杂表单。

前言

在中后台应用中,表单是不可缺少的一部分,相信大家对表单都有一种恐惧感,表单渲染出来比较简单,但是要处理表单联动表单元素状态(编辑,禁用,显示)、表单各种校验等,代码写出来往往会是一大坨,逻辑遍布各种地方,比较难维护而且代码复用性极差。

使用 Antd 进行表单的处理其实已经提高不少效率,直接拷贝一下官方代码就可以出来一个表单,但还是避免不了前面提到的问题,如何优雅地处理表单还是要进行一层封装才行。

我使用 Antd 处理表单经历过三个阶段:粗暴处理 -> 抽象元素 -> 配置渲染。

粗暴处理

需要什么表单组件、表单布局,直接拷贝代码,刷刷刷就出来一个表单,然后需要什么校验,给每个组件配置上,需要进行表单联动的话,监听一下组件 onChange 事件,再修改一下其他组件的值,如果还需要控制组件的状态(编辑态、显示态),那就单独写一个函数渲染这个组件,在里面根据状态进行渲染, 这里就不贴代码了,相信大家也经历过这个阶段,应该比较有画面感。

抽象元素

表单做多了,发现这样粗暴处理,感觉没有一点点追求,都是重复的工作,而且维护成本高。于是找到一些共性,对常用的表单组件进行一层封装,例如 Input,

import 

做的事情主要是把必要但又繁琐的 FormItem 和 getFieldDecorator 封装起来,不用每次重复写,另一方面就是对表单组件的状态进行处理,区分编辑态展示态,这样可以方便切换状态。

封装完需要用到的表单组件后,渲染表单就是对这些表单组件进行组装了:

import 

经过抽象处理后,处理表单就有点感觉了,在不失灵活性的前提下,代码得到比较高的重用,完全在可控之中。

配置渲染

抽象出各种表单组件后,维护起来确实比粗暴处理好多了,只要维护一个组件库,每个项目都按这样开发表单就好了。但如果只止于此的话,体现不出一名优秀的工程师的气质,感觉这个方案不具有通用性,也不够强大,还有比较大优化空间。

在抽象表单组件的时候,已经有想过使用 json 配置的方式进行渲染,例如:

const 

但感觉会不够灵活,有几个问题比较担忧的:

  1. 如何处理表单联动问题?渲染组件都是一个循环的,如何捕获到组件的 onChange 事件?又如何修改其他组件的属性值?
  2. 如果内置的表单组件不满足需求,业务上如何定制自己的组件?
  3. 这样能覆盖多少场景?有没有信心面对复杂的表单?

持续了一段时间,没有去思考如何解决这几个问题,后来业务上遇到特别多的表单需求,不得不重新思考下,这几个问题也是可以解的,然后做了一个表单配置渲染库,解决了业务上问题,经历了半年多的考验,证明思路是对的,才进行了开源与大家交流,也就是 afms,下面简单介绍一下它。

简单介绍

对于表单配置渲染,相信已经有很多人做过了,道理大家都懂,就是约定一份配置格式,然后根据规范渲染出表单元素,但往往都是只能满足简单的场景,而且使用的体验不太友好,可能只能用在搭建简单表单页面的场景。在做之前也调研过市面上做表单配置渲染的库,都不合自己的口味。所以只能自己设计一版,自己用得爽才是硬道理。

在 afms 中,有几个关键概念:

  • FormRender: 整个表单的容器,读取配置,进行表单总体布局,托管所有组件的事件,获取表单元素的值。
  • FormRenderCore表单元素渲染器,负责根据配置数据渲染出表单元素,可实时注册表单元素。
  • Field表单元素,组件都是基于 Antd 进行包裹一层,组件的配置和 Antd 保持一致,可定义自己的业务组件。

大概结构代码上演示:

<

下面是 formConfig 的配置格式:

{
  

配置的设计亮点在于无缝对接 Antd Form 和官方组件的属性配置,外层的配置则为 Form 的配置,主要控制表单整体性的东西,如布局、表单项属性配置。

现在来看看 fields 几个配置,

  • formItem: Antd Form 里 Form.Item 的配置。
  • decorator: Antd Form 里 getFieldDecorator 的配置。
  • config: Antd 组件的属性配置,如果为自定义组件,则为自定义组件的属性配置。

在设计上基本沿用 Antd 里的配置,额外的配置用到实现自己想做的功能,主要是增加了表单元素的状态切换(编辑态、展示态、禁用态)和增强了表单布局功能, 所以使用 Antd 搭建出来的表单,都可以写成一份配置数据。

常用功能

下面介绍一下,如果利用 afms 实现表单常用的功能,下面只展示核心代码,详细请查看在线 Examples。

基础渲染

表单的基础处理,主要流程是 定义配置数据 -> 渲染 -> 提交 -> 获取数据,这也是表单配置渲染具有的基本功能,下面看看使用 afms 渲染表单基本的框架:

const 

详细请查看样例 BasicForm。

表单布局

表单的布局状态除了支持 Antd Form 里的三个 'horizontal' | 'vertical' | 'inline' 外,新增了 'multi-column' 属性,主要支持多列布局,因为很多时候需要两列或者三列,甚至更复杂,和表格的布局类似,有时需要横跨多行、横跨多列,所以加了这个配置。多列布局这个功能我觉得 Antd 可以内置,目前我这里临时做了,主要是表单需求中比较多这样的场景。

const 

这里定义表单有三列,每个表单元素占据三分之一的宽度,但是 memo 定义占据两列,所以它占据了三分之二的宽度。

详细请查看样例 FormLayout 和 ComplexLayout。

表单元素状态

不知大家有没有遇到这样的需求,一个表单,可以支持一直编辑的,即一开始展示已经提交过的数据,点击编辑就可以编辑表单的内容。一般做法可能是写两个模块,一个模块是编辑功能,另一个模块是展示数据的,一开始我也是这样的做的,但这样做两个模块的逻辑是有很大重合的,维护起来也比较麻烦,因为这个需求,才有了上面提到的抽象出表单元素,这样使用的话就可以传 status 属性,根据 status 来渲染不同状态。

<

目前 afms 里内置的表单元素都是有三种状态的,编辑态展示态禁用态,直接指定即可,默认是 edit 状态。

const 

当然,除了可以独立指定表单元素的状态,也可以全局指定整个表单的状态,全局状态可以被局部的状态覆盖。

const formConfig = {
  status: 'edit',
  fields: [
    { field: 'input', id: 'name' },
    { field: 'input', id: 'memo', status: 'preview', value: '1234' },
  ],
}

这时虽然指定了表单状态为 编辑态,但是 memo 这个元素是展示态。

详细请查看样例FormFieldStatus。

表单联动

表单联动的问题非常常见,真正的表单需求很少有静态的表单。联动的场景比如一个表单元素修改了,会影响另一个表单元素的值。

第一种方法,监听 FormRenderonChange 方法,它托管了所以表单元素的 onChange 事件,所以能监听到目标元素的改变,然后通过修改 formConfig 来修改其他元素。

function 

第二种方法,直接在 json 配置数据里定义 filed 的 onChange 事件,通过 form.setFieldValue 来改变其他元素。

const 

详细请查看样例 FormLinkage。

表单组合

有这样一个场景,一个表单是由多个模块组成的,如何使用配置描述?这时可以看做是多个表单,每个表单可以独立渲染,但表单的数据控制还是有一个整体的容器。

import 

前面也提到,FormRenderCore 是表单渲染器,FormRender 只是表单的容器,如果直接在 FormRender 里指定配置数据的话,FormRender 默认渲染一个 FormRenderCore,不指定配置数据的话,你可以在它内部使用 FormRenderCore 随意渲染表单,收集表单数据还是由 FormRender 来收集,这样就可以实现多个表单组合的情况了。

详细请查看样例 MutipleForm。

表单组装

在前期评估中,如果觉得这表单需求,使用配置数据进行渲染,会有限制,满足不了某种需求,则可以回归到原始的办法,表单元素组装!

import 

这个方法是一个万能的方法,不是做 afms 的初衷,但还是能提供了一个选择,可以不使用配置数据进行表单渲染。

详细请查看样例 AssembleFormField。

自定义表单元素

除非业务非常简单,内置的表单元素已经足够用来渲染表单,但真实情况肯定是不会满足的,这时配置就需要支持自定义自己的表单元素。

在 fields 的配置中,field 的值可以字符串或者是一个组件,如果是字符串,则是定义内置的表单元素,如果是一个组件,则是定义自己的表单元素:

import 

自定义自己的表单元素也是有规范的,可以继承 BaseField,然后实现自己的方法即可:

import 

详细请查看样例 CustomFormField。

注册表单元素

注册表单元素,主要是定义 field 的类型:

import 

这样就可以全局定义好 field 的类型, 这样在配置中 field 字段保持是字符串,这里既可以注册自定义的表单元素,也可以覆盖内置的表单元素。

提供这个功能,一方面主要优化使用体验,全局注册好的话,就不用在每次的配置都需要引用自定义表单元素,直接配置 field 的类型即可。

另一方面主要是考虑到一个场景,如果是团队合作的话,有很多业务的表单组件需要进行共用,那有两种方法,

  1. 建立公共的组件库,每个项目需要的话直接注册即可。
  2. 建立自己团队的表单配置渲染库,底层引用的是 afms,里面定义业务的表单元素。

满足这种场景,注册表单元素这个功能显得非常有必要。

结语

使用 afms 渲染表单,不敢说能满足100%的表单需求,但非常有自信地说能满足99%的表单需求,因为表单组装那个方法是万能的,剩下那1%不满足可能就是个人选择偏好了。

虽然是基于 Antd 做的,其实思想都是一样的,应用到其他组件库一样的道理,也可以同时支持多个组件库,只不过觉得没有必要。

可能有人会笑,觉得使用配置数据渲染表单没啥必要,还不如随心所欲地拷代码组装出来,其实我也是这样笑过来的。

希望大家能花一点时间尝试用一下,如果喜欢的话,欢迎交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值