• Antd Procomponent 之 proForm - 高级表单


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

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

    ProForm 高级表单

    • 使用 initialValues设置默认值。

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

    • ProForm 的 onFinish 是个 Promise。

    • 使用 onValuesChange 监听某个值。

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

    1. // 设置整体默认值
    2. // 设置单个控件的
    3.  console.log(changeValues)}>
    4.   "prop"/>
    5. // 相互依赖的组件联动
    6.   'name']}>
    7.   {({ name }) => {
    8.     return (
    9.       
    10.         options={[
    11.           {
    12.             value: 'chapter',
    13.             label: '盖章后生效',
    14.           },
    15.         ]}
    16.         width="md"
    17.         name="useMode"
    18.         label={`与《${name}》合同约定生效方式`}
    19.       />
    20.     )
    21.   }}
    22. // 使用自定义组件
    23.   "switch" label="Switch" valuePropName="checked">
    24.     
    25.   

    ProFormFields 表单项

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

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

    1. const ProFormText = (props) => {
    2.   return (
    3.     
    4.       
    5.     
    6.   )
    7. }

    组件列表

    51b962b4530cb8e9e2cadacf8d86538a.jpeg

    ProFormList 数据结构化

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

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

    • ProFormDependency 数据依赖的相关组件

    ProFormList

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

    ProFormList API

    e7a628cb40f47cc2a406d8cdf367dde1.jpeg

    actionRef 操作 & actionGuard 拦截器

    1. const actionRef = useRefstring }>>();
    2. const actionGuard = {
    3.   beforeAddRow: async (defaultValue, insertIndex, count) => {
    4.     return new Promise((resolve) => {
    5.       console.log(defaultValue?.name, insertIndex, count);
    6.       setTimeout(() => resolve(true), 1000);
    7.     });
    8.   },
    9.   beforeRemoveRow: async (index, count) => {
    10.     const row = actionRef.current?.get(index as number);
    11.     console.log('--->', index, count, row);
    12.     return new Promise((resolve) => {
    13.       if (index === 0) {
    14.         resolve(false);
    15.         return;
    16.       }
    17.       setTimeout(() => resolve(true), 1000);
    18.     });
    19.   },
    20. };
    21. return (
    22.   /**
    23.    * @name 获取到 list 操作实例
    24.    * @description 可用删除,新增,移动等操作
    25.    *
    26.    * @example  actionRef?.current.add?.({},1);
    27.    * @example  actionRef?.current.remove?.(1);
    28.    * @example  actionRef?.current.move?.(1,2);
    29.    * @example  actionRef?.current.get?.(1);
    30.    */
    31.   <>
    32.     
    33.       
    34.         type="primary"
    35.         onClick={() => {
    36.           const list = actionRef.current?.getList();
    37.           actionRef.current?.add({
    38.             name: '新增' + list?.length,
    39.           });
    40.         }}
    41.       >
    42.         增加一行
    43.       
    44.       
    45.         danger
    46.         onClick={() => {
    47.           actionRef.current?.remove(1);
    48.         }}
    49.       >
    50.         删除一行
    51.       
    52.       
    53.         onClick={() => {
    54.           actionRef.current?.move(10);
    55.         }}
    56.       >
    57.         移动到第一行
    58.       
    59.       
    60.         type="dashed"
    61.         onClick={() => {
    62.           const row = actionRef.current?.get(1);
    63.           console.log(row);
    64.         }}
    65.       >
    66.         获取一行数据
    67.       
    68.       
    69.         type="dashed"
    70.         onClick={() => {
    71.           const row = actionRef.current?.getList();
    72.           console.log(row);
    73.         }}
    74.       >
    75.         获取所有数据
    76.       
    77.     
    78.     
    79.       "useMode" name="name" label="姓名" />
    80.     
    81.   
    82. )

    ProFormFieldSet

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

    1.   name="list"
    2.   label="组件列表"
    3.   // 支持 两种方式,type="group" 会用input.group 包裹
    4.   // 如果不配置 默认使用 space
    5.   type="group"
    6.   transform={(value: any) => ({ startTime: value[0], endTime: value[1] })}
    7. >
    8.   "md" />
    9.   "md" />
    10.   "md" />

    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 } }

    1. 'name']}>
    2.   {({ name }) => {
    3.     return (
    4.       
    5.         options={[
    6.           {
    7.             value: 'chapter',
    8.             label: '盖章后生效',
    9.           },
    10.         ]}
    11.         width="md"
    12.         name="useMode"
    13.         label={`与《${name}》合同约定生效方式`}
    14.       />
    15.     );
    16.   }}

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

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

    - END -

    关于奇舞团

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

    cfcdd654d7194b3ce17f8689c8346a5b.png

  • 相关阅读:
    Python基础教程:装饰器的详细教程
    【数据库】MySQL分页查询
    vcpkg切换 Visual Studio 版本
    【数据结构】经典八大排序(Plus版)
    Java开发者必备:支付宝沙箱环境支付远程调试指南
    AI:11-基于深度学习的鱼类识别
    总建面64万平,配3所幼儿园+54班九年制学校,坪山江岭竹元规划
    Java代码中如何判断一个HashMap对象是否为空呢?
    解决:brew install xxx 时出现“No such file or directory @ rb_sysopen - ”
    局域网https自签名教程
  • 原文地址:https://blog.csdn.net/qiwoo_weekly/article/details/134257842