基于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个月前开发好了,但是一直没有写文章推广,因为我失业了,最近才找到新工作,有点时间才写了这篇文章。

谢谢!

相关推荐
Jiaberrr几秒前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
everyStudy25 分钟前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
城南云小白25 分钟前
web基础+http协议+httpd详细配置
前端·网络协议·http
前端小趴菜、26 分钟前
Web Worker 简单使用
前端
web_learning_32128 分钟前
信息收集常用指令
前端·搜索引擎
tabzzz36 分钟前
Webpack 概念速通:从入门到掌握构建工具的精髓
前端·webpack
200不是二百1 小时前
Vuex详解
前端·javascript·vue.js
滔滔不绝tao1 小时前
自动化测试常用函数
前端·css·html5
码爸1 小时前
flink doris批量sink
java·前端·flink
深情废杨杨1 小时前
前端vue-父传子
前端·javascript·vue.js