基于Antd Form组件的二次封装,配置化生成表单、一级列表二级列表功能

前言

在前端中后台的开发中,常见的业务场景是对表单的处理。对于简单、交互少、联动少的业务场景直接使用antd提供的Form组件就可以,对于追求性能,需要复杂表单生成的时候可以使用 formily 开源库,但其付出的学习成本会更高。

今天介绍一个本人开源的项目,介于两者之间的一个便捷、高效、易于理解、且功能相对完整、适用于绝大多数业务场景开发的一个库。

这是一个纯前端的项目

github地址

github.com/CMG-CEO/ant...

github演示地址

cmg-ceo.github.io/antdform.gi...

功能一:配置化生成表单

简化了Form组件的写法,原来写法,要在每一个Form里面写Form.item 并在Form.Item 内写一堆配置项

jsx 复制代码
<Form
  name="basic"
  labelCol={{ span: 8 }}
  wrapperCol={{ span: 16 }}
  initialValues={{ remember: true }}
  onFinish={onFinish}
  onFinishFailed={onFinishFailed}
  autoComplete="off"
>
  <Form.Item
    label="标题"
    name="title"
    rules={[{ required: true, message: 'Please input your username!' }]}
  >
    <Input />
  </Form.Item>

  <Form.Item
    label="备注"
    name="remark"
    rules={[{ required: true, message: 'Please input your password!' }]}
  >
    <Input.Password />
  </Form.Item>
</Form>

我们对其进行了精简化操作 ,将需要传入的配置项抽象成一个数组对象 fields ,进行传递,这样带来的好处就是代码书写更加清晰,同时使用了数组对象形式,带来更加便捷的修改使用。

jsx 复制代码
  <Form form={form} layout="vertical" initialValues={{}}>
   <FormItem
    ref={form}
    fields={[
      {
        type: 'text',
        required: true,
        label: '标题',
        code: 'title',
        span: 24,
      },
      {
        type: 'textarea',
        label: '备注',
        code: 'remark',
        span: 10,
      },
    ]}
    labelCol={24}
    wrapperCol={24}
  ></FormItem>
</Form>
  • ref 为表单实例项
  • fields 表单内每一控件的配置信息
  • labelCol、wrapperCol 每一项的标签和输入控件的布局样式

功能二 采用组的概念实现数据联动

表单之间的数据联动是非常常用的功能,例如一个表单中有一个选择控件,希望选择一的时候后面展示输入框一,选择二的时候后面展示选择框二。

这里的设计模式是:

将所有的表单控件都传递到fields字段中,并传入相对应的组的名称。

就拿上面例子来说,fields传入所有有可能展示的对象(选择框控件,输入框一、输入框二),在选择控件的点击事件中,设置对应的 groupValue 值,在输入框一、二中 group 设置不同组的名称。

这样是通过组关联起来group、 groupValue支持字符串数组

同样一个控件可由多个规则控制。

jsx 复制代码
const [groupValue, setGroupValue] = useState([]);
        ...
<FormItem
  ref={form}
  fields={[
    {
      type: 'select',
      required: true,
      label: '规则选择(一)',
      code: 'rules1',
      span: 24,
      options: [
        {
          id: '1-1',
          name: '规则1-1',
        },
        {
          id: '1-2',
          name: '规则1-2',
        },
      ],
      onChange: (val) => {
      // 获取选中的值,根据业务需求更新组的规则
        const index = groupValue.findIndex((i) => i === '1-1' || i === '1-2');
        if (index > -1) {
          groupValue.splice(index, 1, val);
        } else {
          groupValue.push(val);
        }
        setGroupValue([...groupValue]);
      },
    },
    {
      type: 'select',
      required: true,
      label: '规则选择(二)',
      code: 'rules2',
      span: 24,
      options: [
        {
          id: '2-1',
          name: '规则2-1',
        },
        {
          id: '2-2',
          name: '规则2-2',
        },
      ],
      onChange: (val) => {
      // 获取选中的值,根据业务需求更新组的规则
        const index = groupValue.findIndex((i) => i === '2-1' || i === '2-2');
        if (index > -1) {
          groupValue.splice(index, 1, val);
        } else {
          groupValue.push(val);
        }
        setGroupValue([...groupValue]);
      },
    },
    {
      type: 'text',
      label: '我是规则1-1',
      code: 'rule1-1',
      span: 24,
      // 所属组
      group: ['1-1'],
    },
    {
      type: 'text',
      label: '我是规则1-2或2-1',
      code: 'rule1-2,2-1',
      span: 24,
      // 所属组
      group: ['1-2', '2-1'],
    },
    {
      type: 'text',
      required: true,
      label: '规则2-2 必填',
      code: 'rule2-2',
      span: 24,
      group: ['2-2'],
    },
    {
      type: 'text',
      label: '规则不是2-2 非必填',
      code: 'rule2-2',
      span: 24,
      group: ['1-1', '1-2', '2-1'],
    },
  ]}
  groupValue={groupValue}
  labelCol={24}
  wrapperCol={24}
></FormItem>

功能三 一级列表

Antd Form动态增减表单项基础上衍生出的功能

一级列表的功能和 Antd 基本一致,将Antd的代码进行封装使其更加清晰简洁

这里,level1 的字段内容就是你要新增的一级列表的内容

同时这里封装了addLevel1方法,你只需要调用它就可以生成

jsx 复制代码
import FormItem, { FormWrapCard, addLevel1 } from '@/components/FormItem';
...
const addHandle = () => {
    // 将form实例,一级列表的名称,一级列表需要赋值的初始值传递下去
    addLevel1(form, ['list'], {});
};
<Form form={form} layout="vertical" initialValues={{}}>
    <FormItem
      ref={form}
      fields={[
        {
          type: 'text',
          required: true,
          label: '标题',
          code: 'title',
          span: 24,
        },
      ]}
      level1={{
        name: ['list'],
        fields: [
          {
            type: 'text',
            label: '键',
            code: 'key',
            span: 12,
          },
          {
            type: 'text',
            label: '值',
            code: 'value',
            span: 12,
          },
        ],
        WrapComponent: FormWrapCard,
        // 列表的复制功能
        wrapCopy: true,
        // 列表的移动功能
        wrapMove: true,
        // 列表的是否展示label,不展示时显示类似于表格
        openLabel: true,
      }}
      labelCol={24}
      wrapperCol={24}
    ></FormItem>
</Form>
<Button onClick={addHandle}> 添加一项</Button>

功能四 二级列表

在一级列表的功能上,进一步实现二级列表的开发,及嵌套在一级列表中的列表

其中使用 addLevel2 方法,生成

jsx 复制代码
import FormItem, { FormWrapCard, addLevel1, addLevel2 } from '@/components/FormItem';
// ...
const addHandle = () => {
    addLevel1(form, ['list'], {});
  };
const addHandleLevel2 = (field) => {
const name = ['level2'];
    // 新增第二级的List
    // 将form实例,二级列表的名称(第一项为一级列表的名称),二级列表需要赋值的初始值传递下去
    addLevel2(form, ['list', field.name], name, {});
};
return (
<>
  <Divider orientation="left">表单二级</Divider>
  <Form form={form} layout="vertical" initialValues={{}}>
    <FormItem
      ref={form}
      level1={{
        name: ['list'],
        fields: [
          {
            type: 'text',
            label: '我是Level1',
            code: 'level1',
            span: 24,
          },
        ],
        WrapComponent: FormWrapCard,
        openLabel: true,
        wrapAction: (data) => <PlusCircleOutlined onClick={() => addHandleLevel2(data)} />,
      }}
      level2={{
        name: ['level2'],
        fields: [
          {
            type: 'text',
            label: '我是Level2',
            code: 'level1',
            span: 10,
          },
        ],
        openLabel: true,
      }}
      labelCol={24}
      wrapperCol={24}
    ></FormItem>
  </Form>
  <Button onClick={addHandle}> 添加一项</Button>
</>
  );

功能五 一级列表和二级列表的数据联动

这一块就参考Readme 文档,写的还算详细

待完善

后续还要完成如下功能的开发

  • 1、主分支适配 Antd5 版本的,现有的移入Antd4版本分支 (看官网 5在表单控件上改动量并不大)

  • 2、上TypeScript,现有还是JavaScript开发,后续用上 TypeScript 给与更多提示和完善

最后

希望大家点点star,也欢迎大家提出意见一起改进!

其实项目4-5个月前开发好了,但是一直没有写文章推广,因为我失业了,最近才找到新工作,有点时间才写了这篇文章。

谢谢!

相关推荐
崔庆才丨静觅11 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606112 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了12 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅12 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅13 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅13 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment13 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅13 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊13 小时前
jwt介绍
前端
爱敲代码的小鱼13 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax