写点什么

「前端组件开发」越折腾越有趣,封装了一个表单组件

作者:叶一一
  • 2022-10-14
    北京
  • 本文字数:2575 字

    阅读完需:约 1 分钟

「前端组件开发」越折腾越有趣,封装了一个表单组件

折腾前

我在封装详情页功能的时候,其实最早的雄心壮志是做低代码平台。看了几篇文章,再看看自己的小键盘以及手里的项目排期,就放弃了。我和我的梦想终究是隔着时间、人力、能力等多重重险阻。

但是,我转念一想,如果把前端的功能简化,不就有时间做低代码平台的开发了吗?对于自己的机智,反手就是一个赞。

于是开始计划,最大化的模块化和组件化前端功能,这样一来,每次新需求开发就会非常的便捷。而后台系统,最复杂也最啰嗦的就是表单功能,所以我准备将表单做成组件化的。

表单功能不用再重复的码一些个输入框、下拉项、日期控件等代码,是不是节省了很多时间,节省出来的时间又可以去研究低代码开发,是不是离财富自由更近了一步。(✧◡✧)

基于 React 框架开发,使用的 antd UI 组件库。

整体设计

功能介绍

antd 提供的 Form 表单控件,已经集成了数据录入、校验以及对应样式等。但是我们实际开发的时候,后台系统的添加、编辑、其他数据录入等表单弹窗,内容项大多是 Input、Radio、CheckBox 等,每次开发都重复码一些代码。所以我根据日常开发经验,将常规的表单项做了进一步的封装处理。

封装处理之后,只需将表单项类型、key 值等关键变量放到一个数组对象中,通过 props 传递到表单组件中即可。

当表单填写完成之后,填写的数据会通过 callback 函数回传到表单弹窗中。

参数介绍


表单项类型

目前支持的表单项类型如下,未来如果有新的开发思路,会继续增加

细节处理

细节处理只放关键代码,完整代码已经放到 github 上了,github 地址在文末。下面主要将设计思路和实现方式

类型区分

list 数组,根据每个元素的 fieldtype 区分不同的展示内容。

{  list.map((formItem, formIndex) => {    return (      <Fragment key={formIndex}>        {formItem.fieldtype === 'input' && inputContent(formItem)}        {formItem.fieldtype === 'inputNumber' && inputNumberContent(formItem)}        ......      </Fragment>    );  });}
复制代码

input

  • 输入框使用的 antd 提供的 Input 组件。

  • 如果输入框类型的内容项,展示内容不单单是输入框,可能还包含其他的比如提示文案,可以使用 children 进行内容替换。

/** * 输入框类型 * @param {object} item 表单项 */const inputContent = item => {  return (    <>      {item.children ? (        item.children      ) : (        <Form.Item label={item.label} name={item.key} rules={item.rules} disabled={item.disabled}>          <Input placeholder={`请输入${item.label}`} />        </Form.Item>      )}    </>  );};
复制代码

inputNumber

  • 输入框使用的 antd 提供的 InputNumber 组件。

  • 数字类型的输入框的特别之处在于输入的数值可以设置最小值和最大值、小数点、每次可以改变的步数。这些都可以通过设置对应的属性进行控制。

  • 数字类型的输入框支持展示单位,通过 unit 变量控制单位的展示。

<Form.Item label={item.label} className={classnames({ required: item.required })}>  <Form.Item noStyle name={item.key} rules={item.rules} disabled={item.disabled}>    <InputNumber style={{ width: '50%' }} step={item.step} min={item.min} max={item.max} precision={item.precision} />  </Form.Item>  {item.unit && <span style={{ marginLeft: '10px' }}>{item.unit}</span>}</Form.Item>
复制代码

date

  • 日期类型使用的 antd 提供的 DatePicker 组件。

  • 日期类型支持不同的时间展示方式,通过 format 变量实现。

  • 日期类型可以设置可选时间范围,可选范围包括起日和止日,也可单独设置起日或止日。

  • 写文档的时候突然意识到,实际日期类型也可以支持日期精确到年或是月或是日,目前组件没有实现这个功能,后续实现之后再更新文档。(灵感就是这么一瞬间就来了)

select

  • 下拉选择器类型使用的 antd 提供的 Select 组件。

  • 下拉选择器操作一般获取的是 value,如果需要拿到选中的节点文本 label,通过 onChange 时间设置 option 变量的值为选择的下拉项的值。

  • 有一种特殊情况,当下拉项选择其他时,需要输入其他选项的具体值,所以增加了可输入其他的文本域功能。

{/* 下拉项中有需要文本输入的情况 */}{item.textArea.code && item.option.value === item.textArea.code ? textAreaContent(item.textArea) : null}
复制代码

checkbox

  • 多选框类型使用的 antd 提供的 Checkbox 组件。

radio

  • 单选框类型使用的 antd 提供的 Radio 组件。

  • 有一种特殊情况,当单选项选择否或拒绝时,需要输入原因或者说明,所以增加了可输入其他的文本域功能。

textArea

  • 文本域类型使用的 antd 提供的 Input.TextArea 组件。

  • 当文本域类型表单项和其他表单项组合展示时,展示的布局值需要和组合的表单项一致,所以根据 type 类型做了特殊处理。

let areaLayout = {};if (type === 'other') {  areaLayout = { wrapperCol: { offset: layout.labelCol, span: layout.wrapperCol } };  label = null;}
复制代码

text

纯展示类型,展示具体内容即可。

如何使用

引入组件

  • 一般公共组件会放在 components。完整的代码已经放 github 上了,github 地址在文末。,这里不在重复,主要将一下实现思路。

  • data,基础数据对象,里面放一些表单初始化的数据,比如编辑的时候,表单需要回显之前填过的数据,所以我把这部分数据放到了 data 里面。

  • list,这个是重点,它是一个数组对象,放完整的表单数据,所有需要展示的表单项都要放到 list 数组中,

  • callback,是一个回调函数,提交表单时,需要请求后端提供的接口进行数据上报。callback 函数中的参数 value 包含所有表单项的操作值。

  • getFormRef,是一个操作函数,有一些弹窗的操作按钮需要特殊处理,不是通过 From 组件上的 onFinish 方法进行的操作,所以需要将 formRef 返回到弹窗中,获取实际的操作。

import BaseFormUI from '@/components/BaseFormUI';......const config = {  data: {    ...data,    initFieldsValueFlag: true,  },  list: list,  getFormRef: getFormRef,  callback: callback,};......<BaseFormUI {...config} />
复制代码

弹窗展示


image


数据提交

如果后端接口没有特殊要求,value 对象中的数据基本就满足了,如果需要其他值可以从 list 中获取。


image


总结

github 地址:react-antd-manage

功能完成之后,发现没有自己最开始设想的那么复杂。当然了,也跟功能的兼容程度有关系,不适用特别复杂的表单,比如表格类的表单。

未来希望伴随着学习和进步,进一步完善表单组件。

发布于: 2022-10-14阅读数: 34
用户头像

叶一一

关注

掘金优秀创作者 2022-09-01 加入

非职业传道受业解惑前端程序媛,华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。

评论

发布
暂无评论
「前端组件开发」越折腾越有趣,封装了一个表单组件_前端_叶一一_InfoQ写作社区