{"id":21195626,"url":"https://github.com/qiqiboy/react-antd-formutil","last_synced_at":"2025-07-10T04:30:29.030Z","repository":{"id":49365473,"uuid":"145845853","full_name":"qiqiboy/react-antd-formutil","owner":"qiqiboy","description":"Happy to use react-formutil in the project based on ant-design ^_^","archived":false,"fork":false,"pushed_at":"2020-12-08T08:33:36.000Z","size":13701,"stargazers_count":16,"open_issues_count":2,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-05T18:12:26.929Z","etag":null,"topics":["ant-design","ant-design-form","antd","antd-form","react-component","react-form","react-formutil"],"latest_commit_sha":null,"homepage":"http://github.boy.im/react-antd-formutil/demo/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qiqiboy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-23T11:44:24.000Z","updated_at":"2022-07-25T02:55:01.000Z","dependencies_parsed_at":"2022-09-26T20:30:37.473Z","dependency_job_id":null,"html_url":"https://github.com/qiqiboy/react-antd-formutil","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/qiqiboy/react-antd-formutil","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiqiboy%2Freact-antd-formutil","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiqiboy%2Freact-antd-formutil/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiqiboy%2Freact-antd-formutil/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiqiboy%2Freact-antd-formutil/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qiqiboy","download_url":"https://codeload.github.com/qiqiboy/react-antd-formutil/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qiqiboy%2Freact-antd-formutil/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264128845,"owners_count":23561798,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ant-design","ant-design-form","antd","antd-form","react-component","react-form","react-formutil"],"created_at":"2024-11-20T19:29:18.550Z","updated_at":"2025-07-10T04:30:28.624Z","avatar_url":"https://github.com/qiqiboy.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-antd-formutil\n\n[![npm](https://img.shields.io/npm/v/react-antd-formutil.svg?style=flat)](https://npm.im/react-antd-formutil)\n[![peerDependencies](https://img.shields.io/npm/dependency-version/react-antd-formutil/peer/react.svg?color=yellowgreen)](https://reactjs.org)\n[![definitionTypes](https://img.shields.io/npm/types/react-antd-formutil.svg)](https://github.com/qiqiboy/react-antd-formutil/blob/master/index.d.ts)\n[![gzip](https://img.shields.io/bundlephobia/minzip/react-antd-formutil.svg)](https://npm.im/react-antd-formutil)\n[![download](https://img.shields.io/npm/dm/react-antd-formutil.svg)](https://npm.im/react-antd-formutil)\n[![issues](https://img.shields.io/github/issues/qiqiboy/react-antd-formutil.svg)](https://github.com/qiqiboy/react-antd-formutil/issues)\n[![license](https://img.shields.io/github/license/qiqiboy/react-antd-formutil.svg)](https://github.com/qiqiboy/react-antd-formutil/blob/master/LICENSE)\n[![github](https://img.shields.io/github/last-commit/qiqiboy/react-antd-formutil.svg)](https://github.com/qiqiboy/react-antd-formutil)\n[![github](https://img.shields.io/github/release-date/qiqiboy/react-antd-formutil.svg)](https://github.com/qiqiboy/react-antd-formutil/releases)\n[![github](https://img.shields.io/github/commit-activity/m/qiqiboy/react-antd-formutil.svg)](https://github.com/qiqiboy/react-antd-formutil/commits/master)\n[![github](https://img.shields.io/github/stars/qiqiboy/react-antd-formutil.svg?style=social)](https://github.com/qiqiboy/react-antd-formutil)\n\n[![react-antd-formutil](https://nodei.co/npm/react-antd-formutil.png?compact=true)](https://npm.im/react-antd-formutil)\n\nHappy to use react-formutil in the project based on ant-design@`3`\u0026`4` ^\\_^\n\n在 [ant-design](https://github.com/ant-design/ant-design) 项目，结合 [react-formutil](https://github.com/qiqiboy/react-formutil) 来快速构建表单。**支持所有的`ant-design`输入型（`data-entry`）组件。**\n\n\u003e **如果你在使用其他 react 组件库，可以查阅：**\n\u003e\n\u003e 1.  react-bootstrap [`react-bootstrap-formutil`](https://github.com/qiqiboy/react-bootstrap-formutil) [![npm](https://img.shields.io/npm/v/react-bootstrap-formutil.svg?style=flat)](https://npm.im/react-bootstrap-formutil)\n\u003e 1.  react-md [`react-md-formutil`](https://github.com/qiqiboy/react-md-formutil) [![npm](https://img.shields.io/npm/v/react-md-formutil.svg?style=flat)](https://npm.im/react-md-formutil)\n\u003e 1.  Material-UI [`react-material-formutil`](https://github.com/qiqiboy/react-material-formutil) [![npm](https://img.shields.io/npm/v/react-material-formutil.svg?style=flat)](https://npm.im/react-material-formutil)\n\n\u003c!-- vim-markdown-toc GFM --\u003e\n\n- [安装 Installation](#安装-installation)\n- [使用 Usage](#使用-usage)\n    + [`\u003cFormItem /\u003e`](#formitem-)\n        * [`name`](#name)\n        * [`$defaultValue`](#defaultvalue)\n        * [`$validators`](#validators)\n        * [`itemProps`](#itemprops)\n        * [`$parser`](#parser)\n        * [`$formatter`](#formatter)\n        * [`checked` `unchecked`](#checked-unchecked)\n        * [`$validateLazy`](#validatelazy)\n        * [`$memo`](#memo)\n        * [`validMessage`](#validmessage)\n        * [`valuePropName` `changePropName` `focusPropName` `blurPropName`](#valuepropname-changepropname-focuspropname-blurpropname)\n        * [`getValueFromEvent`](#getvaluefromevent)\n        * [`noStyle`](#nostyle)\n        * [`errorLevel`](#errorlevel)\n    + [`setErrorLevel(level)`](#seterrorlevellevel)\n    + [`支持的组件`](#支持的组件)\n        * [`AutoComplete`](#autocomplete)\n        * [`Checkbox`](#checkbox)\n        * [`Cascader`](#cascader)\n        * [`DatePicker`](#datepicker)\n        * [`InputNumber`](#inputnumber)\n        * [`Input`](#input)\n        * [`Mentions`](#mentions)\n        * [`Pagination`](#pagination)\n        * [`Rate`](#rate)\n        * [`Radio`](#radio)\n        * [`Switch`](#switch)\n        * [`Slider`](#slider)\n        * [`Select`](#select)\n        * [`TreeSelect`](#treeselect)\n        * [`Transfer`](#transfer)\n        * [`TimePicker`](#timepicker)\n        * [`Upload`](#upload)\n    + [`动态className`](#动态classname)\n- [FAQ](#faq)\n    + [`给组件设置的onChange、onFocus等方法无效、不执行`](#给组件设置的onchangeonfocus等方法无效不执行)\n    + [`RangePicker 在safari下假死？`](#rangepicker-在safari下假死)\n    + [`在生产环境(NODE_ENV==='production')部分组件调用有异常？`](#在生产环境node_envproduction部分组件调用有异常)\n    + [`如何正确的使用FormItem嵌套渲染多个节点元素？`](#如何正确的使用formitem嵌套渲染多个节点元素)\n\n\u003c!-- vim-markdown-toc --\u003e\n\n### 安装 Installation\n\n[![react-antd-formutil](https://nodei.co/npm/react-antd-formutil.png?compact=true)](https://npm.im/react-antd-formutil)\n\n**`react-antd-formutil`从`1.0.0`版本开始，同时支持 Ant Design `3.x`和`4.x`版本**\n\n```bash\n# npm\nnpm install react-antd-formutil --save\n\n# yarn\nyarn install react-antd-formutil\n```\n\n### 使用 Usage\n\n\u003e `react-antd-formutil` 整合了 `react-formutil` 的组件，所以可以直接从`react-antd-formutil`中导出所需要的 `react-formutil` 组件。不用单独从 react-formutil 中导出。\n\n先看一个使用示例（点击查看在线完整示例: [react-antd-formutil on codesandbox.io](https://codesandbox.io/s/84y6w5oox2)）：\n\n```javascript\nimport React, { Component } from 'react';\nimport { withForm, FormItem } from 'react-antd-formutil';\nimport { Input, Form } from 'antd'; // 导入antd的Input组件\n\n@withForm\nclass MyForm extends Component {\n    submit = () =\u003e {\n        const { $invalid, $getFirstError, $params } = this.props.$formutil;\n\n        if ($invalid) {\n            alert($getFistError());\n        } else {\n            // submit your data\n        }\n    };\n\n    render() {\n        return (\n            \u003cForm onSubmit={this.onSubmit}\u003e\n                \u003cFormItem\n                    name=\"username\"\n                    itemProps={{\n                        label: 'Username'\n                    }}\u003e\n                    \u003cInput /\u003e\n                \u003c/FormItem\u003e\n            \u003c/Form\u003e\n        );\n    }\n}\n```\n\n`FormItem`是 `react-antd-formuitl` 新增加的组件，`withForm`是`react-formutil`的组件（没错，你可以直接从`react-antd-formutil`中导出`react-formutil`的组件啦）。\n\n只需要将`ant-design`的交互组件，嵌套在`FormItem`下，即可实现自动的表单状态同步。\n\n#### `\u003cFormItem /\u003e`\n\n要实现将`ant-design`的交互组件的值能同步到 react-formutil 的状态中，需要通过 FormItem 这个组件来实现中间态绑定。\n\n它的作用有些类似 antd 中的`getFieldDecorator`方法，但是用法比`getFieldDecorator`更优雅，更 JSX 语法。`FormItem`完全是标签声明式用法，它是对 antd 的`Form.Item`组件的再次封装。\n\n所以`FormItem`会完整实现`Form.Item`所可以显示的校验状态、错误暂时等 UI 变化。\n\n\u003e 如果给 `FormItem` 传递了多个子节点，可能会出现无法非预期的异常情况。你可以了解[`如何正确的使用FormItem嵌套渲染多个节点元素？`](#如何正确的使用formitem嵌套渲染多个节点元素)\n\n**支持传递的属性**\n\n`FormItem`可以接收所有`antd`中的`Form.Item`组件所接收的所有属性，另外还新增以下属性支持：\n\n##### `name`\n\n设置输入项的 name 值，表单项将会以 name 作为 key 收集到 formutil 的状态中。支持嵌套语法 _（同`react-formutil`的`Field`同名参数，可以参考 [name](https://github.com/qiqiboy/react-formutil#name)）_\n\n##### `$defaultValue`\n\n设置该表单项的默认值 _（同`react-formutil`的`Field`同名参数，可以参考[\\$defaultvalue](https://github.com/qiqiboy/react-formutil#defaultvalue)）_\n\n##### `$validators`\n\n设置校验方法 _（同`react-formutil`的`Field`同名参数, 可以参考 [\\$validators](https://github.com/qiqiboy/react-formutil#validators)）_\n\n\u003e 同 react-formutil 的 EasyField，FormItem 也内置了同样的校验规则：\n\n\u003e -   `required` 必填 `required`\n\u003e -   `maxLength` 。最大输入长度，有效输入时才会校验 `maxLength=\"100\"`\n\u003e -   `minLength` 最小输入长度，有效输入时才会校验 `minLength=\"10\"`\n\u003e -   `max` 最大输入数值，仅支持 Number 比较。有效输入时才会校验 `max=\"100\"`\n\u003e -   `min` 最小输入数值，仅支持 Number 比较。有效输入时才会校验 `min=\"10\"`\n\u003e -   `pattern` 正则匹配。有效输入时才会校验 `pattern={/^\\d+$/}`\n\u003e -   `enum` 枚举值检测。有效输入时才会校验 `enum={[1,2,3]}`\n\u003e -   `checker` 自定义校验函数。`checker={value =\u003e value \u003e 10 \u0026\u0026 value \u003c 100 || '输入比如大于10小与100'}`\n\n注：校验属性的值为 `null` 时表示不进行该校验\n\n内置的校验规则无需再次声明，除非规则不符合预期，需要替换，则可以通过`$validators` 传递同名校验方法即可替换默认的。另外，内置的校验规则，如果校验不通过，会尝试去 `validMessage` 匹配错误信息。\n\n##### `itemProps`\n\n该属性为要传递给`Form.Item`组件的配置项：\n\n```javascript\n\u003cFormItem\n    itemProps={{\n        label: 'Username',\n        colon: false\n    }}\u003e\n    \u003cInput /\u003e\n\u003c/FormItem\u003e\n```\n\n##### `$parser`\n\n请参考`react-formutil`中[`$parser`](https://github.com/qiqiboy/react-formutil#parser)介绍。\n\n##### `$formatter`\n\n请参考`react-formutil`中[`$formatter`](https://github.com/qiqiboy/react-formutil#formatter)介绍。\n\n##### `checked` `unchecked`\n\n对于 `\u003cSwitch /\u003e` `\u003cCheckbox /\u003e` `\u003cRadio /\u003e` 这三种组件，其值默认是 checked 属性，为布尔值。可以通过`checked` `unchecked`来设置 checked 状态时所要映射的值：\n\n```javascript\n\u003cFormItem checked=\"yes\" unchecked=\"no\"\u003e\n    \u003cSwitch /\u003e\n\u003c/FormItem\u003e\n```\n\n该示例中， 当 Switch 为开时，获取的值将为 yes。\n\n##### `$validateLazy`\n\n可以用来优化表单的校验速度，请参考： [`$validateLazy`](https://github.com/qiqiboy/react-formutil#validatelazy)\n\n##### `$memo`\n\n可以用来优化当前表单项的性能，避免过多的重复渲染。如果你遇到了表单性能问题，可以尝试该属性来改善。\n\n详细解释和使用、注意事项请参考： [`$memo`](https://github.com/qiqiboy/react-formutil#memo)\n\n##### `validMessage`\n\n设置校验结果的错误信息。\n\n```javascript\n\u003cFormItem\n    name=\"username\"\n    required\n    validMessage={{\n        required: '请输入用户名'\n    }}\u003e\n    \u003cInput /\u003e\n\u003c/FormItem\u003e\n```\n\n##### `valuePropName` `changePropName` `focusPropName` `blurPropName`\n\n该四个参数可以用来设置绑定到组件上的值或者值变动、是否聚焦等事件回调。该项一般不需要设置，`FormItem` 已经针对 `antd` 中的所有 `data-entry` 型组件做了兼容处理。\n\n对于一些特殊场景，例如不需要同步 `focus`、`blur`，则可以通过将该值设为`{null}`来禁用：\n\n```javascript\n//禁用focus、blur状态同步\n\u003cFormItem focusPropName={null} blurPropName={null} name=\"username\"\u003e\n    \u003cInput /\u003e\n\u003c/FormItem\u003e\n```\n\n##### `getValueFromEvent`\n\n请参考 [`getValueFromEvent()`](https://github.com/qiqiboy/react-formutil/blob/master/README.md#getvaluefromevent)\n\n##### `noStyle`\n\n\u003e 该属性从 `v1.1.0` 起可用\n\u003e\n\u003e 该属性同时兼容`antd@3.x` 和`antd@4.x`，都可以使用！\n\n`noStyle`与`AntDesign v4.0`中新版本的`Form.Item`的`noStyle`类似，可以用来控制是否输出`Form.Item`的额外的样式元素。缺省情况下默认值为`false`。\n\n当`noStyle`为`true`时，将会只渲染字段节点本身，但是其表单状态依然会被处理收集。此时，如果其存在父级嵌套的`FormItem`，那么其表达校验状态将会传递给父级的`FormItem`来展现。\n\n这对于连续的紧凑型表单元素将非常有用！可以避免校验错误描述信息都堆叠在一起! **但是没有额外的样式显示，包括表单校验状态都无法显示了。此时可以在其外层包裹一层不带`name`的`FormItem`，这些`noStyle`的表单项就会把他们自身的状态向上进行注册显示了！**\n\n但是有以下几点需要注意：\n\n1. 最外层的`FormItem`不能设置`name`属性，否则将不会被当作子级的校验状态容器\n2. 内层的`FormItem`需要添加相应的`name`值（向表单控制器注册自身）以及`noStyle`属性（不渲染额外的样式，避免和上层冲突）\n\n```typescript\n// 这里不能设置name\n\u003cFormItem label=\"FormItem Group\"\u003e\n    \u003cInput.Group compact\u003e\n        {/* 与普通的FormItem用法一致，只是多了个noStyle */}\n        \u003cFormItem name=\"address.province\" noStyle required validMessage={{ required: 'Province requird!' }}\u003e\n            \u003cSelect placeholder=\"Select province\"\u003e\n                \u003cSelect.Option value=\"Zhejiang\"\u003eZhejiang\u003c/Select.Option\u003e\n                \u003cSelect.Option value=\"Jiangsu\"\u003eJiangsu\u003c/Select.Option\u003e\n            \u003c/Select\u003e\n        \u003c/FormItem\u003e\n\n        \u003cFormItem name=\"address.street\" noStyle required validMessage={{ required: 'Street requird!' }}\u003e\n            \u003cInput style={{ width: '50%' }} placeholder=\"Input street\" /\u003e\n        \u003c/FormItem\u003e\n    \u003c/Input.Group\u003e\n\u003c/FormItem\u003e\n```\n\n以上运行示例请参考 [示例](http://github.boy.im/react-antd-formutil/demo/)\n\n##### `errorLevel`\n\n用来覆盖全局的 errorLevel 设置。参考[`setErrorLevel(level)`](#seterrorlevellevel)\n\n#### `setErrorLevel(level)`\n\n`setErrorLevel` 该方法可以用来全局设置错误信息何时出现，有三个级别可以设置：\n\n-   `0` 当`$dirty` `$touched` `$invalid` 都为 true 时\n-   `1` 当`$dirty` `$invalid` 都为 true 时\n-   `2` 当`$invalid` 为 true 时\n-   `off` 关闭错误显示\n\n默认值为 `1`\n\n\u003e 注意，该方法影响全局，如果只是希望单独对某个表单项进行设置，可以通过`errorLevel`属性进行设置：参考[`errorLevel`](#errorlevel)\n\n```javascript\nimport { setErrorLevel } from 'react-antd-formutil';\n\nsetErrorLevel(0);\n\n// 当关闭错误显示时，errorLevel='off'，你可以手动自行设置错误展示方式：\n\u003cFormGroup\n    name=\"errorOff\"\n    errorLevel=\"off\"\n    itemProps={{\n        validateStatus: $formutil.$errors.errorOff ? 'error' : undefined,\n        help: $formutil.$errors.errorOff ? \u003cdiv\u003e出错啦\u003c/div\u003e : null\n    }}\u003e\n    \u003cInput /\u003e\n\u003c/FormGroup\u003e;\n```\n\n#### `支持的组件`\n\n##### [`AutoComplete`](https://ant.design/components/auto-complete-cn/)\n\n##### [`Checkbox`](https://ant.design/components/checkbox-cn/)\n\n支持`Checkbox.Group`。\n\n##### [`Cascader`](https://ant.design/components/cascader-cn/)\n\n##### [`DatePicker`](https://ant.design/components/date-picker-cn/)\n\n`DatePicker` `TimePicker` `DatePicker.WeekPicker` `DatePicker.MonthPicker` `DatePicker.RangePicker` 等几个日期类组件，都是深度结合了`moment`使用的。如果希望收集到表单中的值是格式化好的时间字符串，可以通过`$parser` `$formatter`实现：\n\n```javascript\n\u003cFormItem name=\"datepicker\" $parser={moment =\u003e moment.format('YYYY-MM-DD')} $formatter={date =\u003e moment(date)}\u003e\n    \u003cDatePicker /\u003e\n\u003c/FormItem\u003e\n```\n\n对于`DatePicker.RangePicker`，由于其值是一个数组，所以需要这样处理：\n\n```javascript\n\u003cFormItem\n    name=\"datepicker\"\n    $parser={moments =\u003e moments.map(moment =\u003e moment.format('YYYY-MM-DD'))}\n    $formatter={dates =\u003e dates.map(date =\u003e moment(date))}\u003e\n    \u003cDatePicker.RangePicker /\u003e\n\u003c/FormItem\u003e\n```\n\n##### [`InputNumber`](https://ant.design/components/input-number-cn/)\n\n##### [`Input`](https://ant.design/components/input-cn/)\n\n##### [`Mentions`](https://ant.design/components/mentions-cn/)\n\n##### [`Pagination`](https://ant.design/components/pagination-cn/)\n\n`Pagination` 并非`antd`所归纳的`data entry`组件，但是其接口设计也可以支持`FormItem`：\n\n```javascript\n\u003cFormItem name=\"page\" $defaultValue={2}\u003e\n    \u003cPagination pageSize={10} total={100} /\u003e\n\u003c/FormItem\u003e\n```\n\n##### [`Rate`](https://ant.design/components/rate-cn/)\n\n##### [`Radio`](https://ant.design/components/radio-cn/)\n\n支持`Radio.Group`。\n\n##### [`Switch`](https://ant.design/components/switch-cn/)\n\n`Switch` `Checkbox`(不包括`Checkbox.Group`) `Radio`(不包括`Radio.Group`)三个组件，可以通过给`FormItem`传递`checked` `unchecked`属性来改变被勾选时所映射到表单状态中的值：\n\n```javascript\n\u003cFormItem checked=\"yes\" unchecked=\"no\"\u003e\n    \u003cSwitch /\u003e\n\u003c/FormItem\u003e\n```\n\n##### [`Slider`](https://ant.design/components/slider-cn/)\n\n##### [`Select`](https://ant.design/components/select-cn/)\n\n##### [`TreeSelect`](https://ant.design/components/tree-select-cn/)\n\n##### [`Transfer`](https://ant.design/components/transfer-cn/)\n\n`Transfer`收集到表单状态中的是`targetKeys`。\n\n##### [`TimePicker`](https://ant.design/components/time-picker-cn/)\n\n参考 [`DatePicker`](#datepicker)\n\n##### [`Upload`](https://ant.design/components/upload-cn/)\n\n`Upload`组件非常特殊，其接受`fileList`对象作为整个组件的状态。而实际业务中，往往只需要获取上传文件的返回的地址，或者一组文件的地址。可以通过`$parser`控制如何获取上传结果的值，并且可以通过`$parser`的第二个回调方法`$setViewValue`来控制`fileList`对象，实现对文件上传数量的控制。\n\n**单个文件上传，获取单个文件上传地址**\n\n```javascript\n\u003cFormItem\n    name=\"upload\"\n    $formatter={url =\u003e\n        url \u0026\u0026 [\n            {\n                url,\n                uid: url,\n                status: 'done',\n                name: url.split('/').slice(-1)[0]\n            }\n        ]\n    }\n    $parser={(info, $setViewValue) =\u003e {\n        // 必不可少，限制只能上传一个文件\n        $setViewValue(info.fileList.slice(-1));\n\n        if (info.file.status === 'done') {\n            return info.file.response.url;\n        }\n    }}\n    itemProps={{ ...formItemLayout, label: 'Upload' }}\n    required\u003e\n    \u003cUpload {...uplodConfig}\u003e\n        \u003cButton\u003e\n            \u003cUploadOutlined /\u003e Click to Upload\n        \u003c/Button\u003e\n    \u003c/Upload\u003e\n\u003c/FormItem\u003e\n```\n\n**多文件列表上传，获取多个文件上传地址数组**\n\n```javascript\n\u003cFormItem\n    name=\"upload\"\n    $formatter={urls =\u003e\n        urls \u0026\u0026\n        urls.map(url =\u003e ({\n            url,\n            uid: url,\n            status: 'done',\n            name: url.split('/').slice(-1)[0]\n        }))\n    }\n    $parser={(info, $setViewValue) =\u003e {\n        // 限制最大上传文件数量为3，如果不需要限制，可以移除该行，或者修改该值\n        $setViewValue(info.fileList.slice(-3));\n\n        return info.fileList.filter(file =\u003e file.status === 'done').map(file =\u003e file.url || file.response.url);\n    }}\n    itemProps={{ ...formItemLayout, label: 'Upload' }}\n    required\u003e\n    \u003cUpload {...uplodConfig}\u003e\n        \u003cButton\u003e\n            \u003cUploadOutlined /\u003e Click to Upload\n        \u003c/Button\u003e\n    \u003c/Upload\u003e\n\u003c/FormItem\u003e\n```\n\n#### `动态className`\n\n`FormGroup`会自动给表单节点增加与该表单项校验状态相关的 className：\n\n-   `has-error`\n-   `is-invalid`\n-   `is-valid`\n-   `is-touched`\n-   `is-untouched`\n-   `is-focused`\n-   `is-unfocused`\n-   `is-dirty`\n-   `is-pristine`\n\n### FAQ\n\n#### `给组件设置的onChange、onFocus等方法无效、不执行`\n\n`FormItem`会覆盖掉直接添加到 antd 组件上的`onFocus` `onBlur` `onChange`方法，所以如果需要这三个事件方法，需要添加到 `FormItem`上：\n\n```javascript\n\u003cFormItem name=\"test\" onChange={ev =\u003e console.log('change', ev)} onFocus={ev =\u003e console.log('focus', ev)}\u003e\n    \u003cInput /\u003e\n\u003c/FormItem\u003e\n```\n\n#### `RangePicker 在safari下假死？`\n\n经过 debug，在`3.8.x`版本上，依然存在对`RangePicker`设置`onFocus` `onBlur`会异常频繁触发（比如在光标经过日期选择面板中每个数字时）的问题。可以禁用`onFocus` `onBlur`状态同步：\n\n```javascript\n\u003cFormItem name=\"datepicker\" focusPropName={null} blurPropName={null}\u003e\n    \u003cDatePicker.RangePicker /\u003e\n\u003c/FormItem\u003e\n```\n\n#### `在生产环境(NODE_ENV==='production')部分组件调用有异常？`\n\n如果在生产环境，发现例如`Checkbox` `Radio` `Switch`等组件无法正确捕获用户输入的值，这种情况一般是由于项目中使用了`babel-plugin-import`插件。\n\n`react-antd-formutil`中是使用 `import { Switch } from 'antd'` 这种写法来调用 `Switch` 组件的，而`babel-plugin-import`插件会将项目源代码中的类似语句，替换成`import Switch from 'antd/lib/switch'`。这两种写法获取到的`Switch`其实并不是严格意义上的相等，前者是对后者的又一层导出封装。\n\n而由于`babel-plugin-import`一般仅仅会配置成仅仅对项目代码进行处理，所以处于项目`node_modules`目录中的`react-antd-formutil`中的语句不会被处理。我们需要通过修改项目 webpack 配置的方式，来使`babel-plugin-import`插件能处理`react-antd-formutil`的代码。\n\n可以编辑项目的 webpack 配置（只需要配置生产环境的构建配置即可），在`rules`模块下添加以下的代码：\n\n```javascript\n{\n    test: /\\.(js|mjs)$/,\n    include: /react-antd-formutil/, // 仅仅处理react-antd-formutil即可\n    loader: require.resolve('babel-loader'),\n    options: {\n        babelrc: false,\n        plugins: [[\n            \"import\",\n            {\n                \"libraryName\": \"antd\"\n            },\n            \"antd\"\n        ]]\n    }\n}\n```\n\n#### `如何正确的使用FormItem嵌套渲染多个节点元素？`\n\n你可以通过给给`children`属性传递`render props`函数，来自由定义要渲染出的节点。但是请注意，当传递一个`render props`函数时，需要手动绑定相关绑定事件和 value 属性！\n\n该`children`函数接受一个`$fieldHandler`的对象，默认情况下其包含`value` `onChange` `onFocus` `onBlur`四个属性，但是如果你给`FormItem`传递了`valuePropName`等属性的话，这个值将会变为你通过`valuePropName`所定义的名字。\n\n更具体解释可以参考 [**react-formutil.\\$fieldHandler**](https://github.com/qiqiboy/react-formutil#fieldhandler)\n\n```typescript\n\u003cFormItem name=\"username\"\u003e\n    {$fieldHandler =\u003e (\n        \u003c\u003e\n            \u003cInput {...$fieldHandler} /\u003e\n            \u003cdiv\u003e其它节点内容\u003c/div\u003e\n        \u003c/\u003e\n    )}\n\u003c/FormItem\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqiqiboy%2Freact-antd-formutil","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqiqiboy%2Freact-antd-formutil","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqiqiboy%2Freact-antd-formutil/lists"}