Antd Procomponent 之 proForm - 高级表单

本文作者系360奇舞团前端开发工程师

ProForm 在原来的 Form 基础上增加一些语法糖和更多的布局设置,帮助我们快速的开发一个表单。同时添加一些默认行为,让我们的表单默认好用。分步表单,Modal 表单,Drawer 表单,查询表单,轻量筛选等多种 layout 可以覆盖大部分的使用场景,脱离复杂而且繁琐的表单布局工作,更少的代码完成更多的功能。

ProForm 高级表单

  • 使用 initialValues设置默认值。

  • 可以使用 ProFormDependency 实现表单联动或者做一些依赖。

  • ProForm 的 onFinish 是个 Promise。

  • 使用 onValuesChange 监听某个值。

  • 如果要使用自定义的组件可以用 Form.Item 包裹后使用,支持与 antd 的 Form混用。

go 复制代码
// 设置整体默认值
<ProForm initialValues={obj} />

// 设置单个控件的
<ProForm onValuesChange={(changeValues) => console.log(changeValues)}>
  <ProFormText initialValue="prop"/>
</ProForm>

// 相互依赖的组件联动
<ProForm>
  <ProFormDependency name={['name']}>
  {({ name }) => {
    return (
      <ProFormSelect
        options={[
          {
            value: 'chapter',
            label: '盖章后生效',
          },
        ]}
        width="md"
        name="useMode"
        label={`与《${name}》合同约定生效方式`}
      />
    )
  }}
</ProFormDependency>
</ProForm>


// 使用自定义组件
<ProForm>
  <Form.Item name="switch" label="Switch" valuePropName="checked">
    <Switch />
  </Form.Item>
</ProForm>

ProFormFields 表单项

ProFormFields 表单项本质上是 Form.Item 和 组件的结合,每个表单项都支持 fieldProps

ProFormText 是 FormItem + Input 的产物,可以类比于以下的代码:

go 复制代码
const ProFormText = (props) => {
  return (
    <ProForm.Item {...props}>
      <Input placeholder={props.placeholder} {...props.fieldProps} />
    </ProForm.Item>
  )
}

组件列表

ProFormList 数据结构化

  • ProFormList 录入结构化的多维数组数据。

  • ProFormFieldSet 录入结构化的一维数组数据。

  • ProFormDependency 数据依赖的相关组件

ProFormList

ProFormList 与 Form.List API 基本相同,自带操作按钮:删除和复制和新增按钮

ProFormList API

actionRef 操作 & actionGuard 拦截器

go 复制代码
const actionRef = useRef<FormListActionType<{ name: string }>>();

const actionGuard = {
  beforeAddRow: async (defaultValue, insertIndex, count) => {
    return new Promise((resolve) => {
      console.log(defaultValue?.name, insertIndex, count);
      setTimeout(() => resolve(true), 1000);
    });
  },
  beforeRemoveRow: async (index, count) => {
    const row = actionRef.current?.get(index as number);
    console.log('--->', index, count, row);
    return new Promise((resolve) => {
      if (index === 0) {
        resolve(false);
        return;
      }
      setTimeout(() => resolve(true), 1000);
    });
  },
};

return (
  /**
   * @name 获取到 list 操作实例
   * @description 可用删除,新增,移动等操作
   *
   * @example  actionRef?.current.add?.({},1);
   * @example  actionRef?.current.remove?.(1);
   * @example  actionRef?.current.move?.(1,2);
   * @example  actionRef?.current.get?.(1);
   */
  <>
    <Space>
      <Button
        type="primary"
        onClick={() => {
          const list = actionRef.current?.getList();
          actionRef.current?.add({
            name: '新增' + list?.length,
          });
        }}
      >
        增加一行
      </Button>
      <Button
        danger
        onClick={() => {
          actionRef.current?.remove(1);
        }}
      >
        删除一行
      </Button>
      <Button
        onClick={() => {
          actionRef.current?.move(1, 0);
        }}
      >
        移动到第一行
      </Button>
      <Button
        type="dashed"
        onClick={() => {
          const row = actionRef.current?.get(1);
          console.log(row);
        }}
      >
        获取一行数据
      </Button>
      <Button
        type="dashed"
        onClick={() => {
          const row = actionRef.current?.getList();
          console.log(row);
        }}
      >
        获取所有数据
      </Button>
    </Space>
    <ProFormList actionGuard={actionGuard} actionRef={actionRef}>
      <ProFormText key="useMode" name="name" label="姓名" />
    </ProFormList>
  </>
)

ProFormFieldSet

ProFormFieldSet 可以将内部的多个 children 的值组合并且存储在 ProForm 中

go 复制代码
<ProFormFieldSet
  name="list"
  label="组件列表"
  // 支持 两种方式,type="group" 会用input.group 包裹
  // 如果不配置 默认使用 space
  type="group"
  transform={(value: any) => ({ startTime: value[0], endTime: value[1] })}
>
  <ProFormText width="md" />
  <ProFormText width="md" />
  <ProFormText width="md" />
</ProFormFieldSet>

ProFormDependency

ProFormDependency 是一个简化版本的 Form.Item,它默认内置了 noStyle 与 shouldUpdate,我们只需要配置 name 来确定我们依赖哪个数据,ProFormDependency 会自动处理 diff 和并且从表单中提取相应的值

name 参数必须要是一个数组,如果是嵌套的结构可以这样配置 name={['name', ['name2', 'text']]}。配置的 name 的值会在 renderProps 中传入。name={['name', ['name2', 'text']]} 传入的 values 的值 为 { name: string,name2: { text:string } }

go 复制代码
<ProFormDependency name={['name']}>
  {({ name }) => {
    return (
      <ProFormSelect
        options={[
          {
            value: 'chapter',
            label: '盖章后生效',
          },
        ]}
        width="md"
        name="useMode"
        label={`与《${name}》合同约定生效方式`}
      />
    );
  }}
</ProFormDependency>

补充:ProForm 和 EditableTable 可以同时使用

注意:ProComponents 专注于中后台的 CRUD, 预设了相当多的样式和行为。这些行为和样式更改起来会比较困难,如果你的业务需要丰富的自定义建议直接使用 Ant Design。

  • END -

关于奇舞团

奇舞团是 360 集团最大的大前端团队,代表集团参与 W3C 和 ECMA 会员(TC39)工作。奇舞团非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。

相关推荐
非凡ghost6 小时前
猫眼浏览器(Chrome内核增强版浏览器)官方便携版
前端·网络·chrome·windows·软件需求
熊文豪11 小时前
Windows安装RabbitMQ保姆级教程
windows·分布式·rabbitmq·安装rabbitmq
搬砖的小码农_Sky11 小时前
Windows操作系统上`ping`命令的用法详解
运维·网络·windows
Kiri霧18 小时前
Rust模式匹配详解
开发语言·windows·rust
程序设计实验室20 小时前
使用命令行删除 Windows 网络映射驱动器
windows
用户31187945592181 天前
Windows 电脑安装 XTerminal 1.25.1 x64 版(带安装包下载关键词)
windows
Logintern091 天前
windows如何设置mongodb的副本集
数据库·windows·mongodb
Chandler241 天前
一图掌握 操作系统 核心要点
linux·windows·后端·系统
ajassi20001 天前
开源 C# 快速开发(十七)进程--消息队列MSMQ
windows·开源·c#
Python私教1 天前
5分钟上手 MongoDB:从零安装到第一条数据插入(Windows / macOS / Linux 全平台图解)
windows·mongodb·macos