{"_id":"@ice/form","_rev":"54-6da958461b82f7651f2675f14952341d","name":"@ice/form","dist-tags":{"beta":"0.1.5-0","latest":"0.1.7"},"versions":{"0.1.0-0":{"name":"@ice/form","version":"0.1.0-0","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.0-0","maintainers":[{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.0-0/build/index.html","dist":{"shasum":"1f130570a7edc9c122dbd3c6db77da1e20c3af71","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.0-0.tgz","fileCount":29,"integrity":"sha512-i08DFRprQzCSe7MyrZWcvu4snvOT0Up9ebMCNf303x2/tEYvFQGb0vbVX1RAh1Iejg7K06dubaRZu0pxwJHyiA==","signatures":[{"sig":"MEQCIE+TWUDMYxA6+sSs2llGEgBFMDS5DvNmDXINV/4aMoaEAiALHeOXwVVsgtitpLaY1DQUkmdU80CRp6WXvB4mfC6FCg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1503823,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7mqdCRA9TVsSAnZWagAAlpcP/RRHbVyBExk1/VSs7S4c\nOm44/989ViOcD3IVGc4WNVpn1wgXCAzzyB5kIpgOO60PViAmYSsnV+h4K9Lm\nILx1VFrPhwDXOJIoYixaV0jGsPMXQRkw0dA6ePSNHd9IFJdD1ddDGiqRZRrP\nZuyj8V20LrPxx/ep5wyeFX2/Vduysiv1DWxceWdyCc0wpgPiiaLdt0QcKj5v\nkEsw2N83c2BReq/QMGXIqNvAl+0N3vf74xzzL2uy5TWFCduSesKiNjpFYR0F\n3HdP9r3DvxGtFZxfGNh0PI2eGuYLl/Kkc5LwldIu9vopfXjZ6/XaUmpIsE8f\nG7KEJVZo88vZ/WH/Kknj9qixNn9OT586LrpiyuaulKMTeQoXyRbUkOwbafZN\n3nrOMfs6QDh+xucb/KIZrZp76ZM1NIAbRQ9iAhHlNeIGvntZ9Vofw5p2t8tA\nMW1rean4Az6+fVZfG1LBDnRZJaWZBDSONvze38bbX1rJG4O+LovFAzkwLV10\nQvZ153sXSaOT/C6eY+mnW4geTmGsy30DskyTp/HXM1b7erim5naBB2vt2VjH\nMz5lXrsUtkXQB9ZpWP0qhhuc3WlEapzypd9TLefELH0KeMlczFh5dp0x7zRk\n2TNFhmDJwqutYluBQfk/4/MgiMp1b09d0RlQrhaCi8frq2gg3jUTGD+l4tAR\nNLeM\r\n=2aHb\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"sobear","email":"sobear.me@gmail.com"},"stylePath":"style.js","_npmVersion":"5.6.0","description":"Example component","directories":{},"_nodeVersion":"8.11.1","dependencies":{"prop-types":"^15.5.8","lodash.find":"^4.6.0","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"componentConfig":{"name":"ice-form","title":"Example component","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.14.4","ice-scripts":"^2.0.0","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.2","ice-plugin-fusion":"^0.1.4","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.1","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.0-0_1559128732467_0.5663161663744101","host":"s3://npm-registry-packages"}},"0.1.0-1":{"name":"@ice/form","version":"0.1.0-1","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.0-1","maintainers":[{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.0-1/build/index.html","dist":{"shasum":"9173b5f231ca8364314fa80fe7a8bcb4d37f961a","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.0-1.tgz","fileCount":29,"integrity":"sha512-6mDNTqU2binfB8e0QgLZi2P1VhGCzPpURAGpxIWhKgcPRcb5MwgmbjLN2JWHSce4EWLFN+akyZMkv9IgAjxQrg==","signatures":[{"sig":"MEQCIAFw5eTNhZfu99FLjsPec8qRTxKTK5EM/iwTajfvAryEAiBhA8DQu+txPvm89iqtQOXPe9fAFCndQE63mcRIXErlxg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1735846,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc71UdCRA9TVsSAnZWagAA6qAQAJCVfnpQ+C4MVrJC3ArK\nfP2OD6pIlV5rNCjNKf9zGJ2rKutoCoo/MO3rD+PmwBVhvQgazZeICX9RfN3R\nhYbBYUErxpIS7eVTHt5vTMUG7f2wi+z09NMavPSIgW7ih8VCyE6w1Er8kHc2\n2RFsJOsFcPbt0HtCAz5olK4i9hxcPjWM0MllAlIoZyjCufmZz6OXWbdQSpxV\nZFMn9ktfZ9GY4m+zHS4df+3XgrKGViyryzo7NpXySVr5ziPlwP6o2LAY79YL\nBUsEj+YhR5zgFZu+IxiaqWv3o97vavnVA5h8j7eUfm2b14kJjNtM4rGS731m\nIG26tSunDa5/12s/sQcXY77uWInZye8MmtGA/pz07BrlA8DSHZhTjFcQ8OdN\nalXjifYcRUYnPe6gpGE2rBPcGLUdlejbtudeTQTWmgBOixCchjuQnauuqdSu\nwMvzrvqBjD6rFZKmY/8LhJJpdJaL2TVjPIUUl9lL2DzFnMceEvY3tfNAna7f\nPgWaUK3zPMwm8JT2D0WNP8ndmHFILM5t8kCxEGJ2GE7gkwrWxny2tgAzkrvs\nRW2U7ap4YboXV+1g2amieuEAIEUb+TrfItGaQ/lrv/2yJzWGwfOxESNDgNMf\nrdY/IKw77dDw4Y0/FQxPb9d6I9NSalBq1oDNkZPR1jxBz+IrM8p3VTXX2vPy\nPjKy\r\n=adCY\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"sobear","email":"sobear.me@gmail.com"},"stylePath":"style.js","_npmVersion":"5.6.0","description":"Example component","directories":{},"_nodeVersion":"8.11.1","dependencies":{"prop-types":"^15.5.8","lodash.find":"^4.6.0","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"componentConfig":{"name":"ice-form","title":"Example component","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.14.4","ice-scripts":"^2.0.0","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.2","ice-plugin-fusion":"^0.1.4","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.1","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.0-1_1559188764856_0.2186396412591478","host":"s3://npm-registry-packages"}},"0.1.0-2":{"name":"@ice/form","version":"0.1.0-2","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.0-2","maintainers":[{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.0-2/build/index.html","dist":{"shasum":"422121826f8419e49d9152951d7dc7ea383df314","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.0-2.tgz","fileCount":26,"integrity":"sha512-xTHQLrBfr0HfONMUwEZcjlAP2gBMJzsVyQ8EL1xSYEywbJ1H/efNZqHvuTIC7PJ6QZAI0rpkmMyraFbviPSsJQ==","signatures":[{"sig":"MEQCIEYe7Ro2Hlhx67D/lGF9J6g2KidKkoIpXTq/Us8ioWfQAiAPaFK1OYlLXsA2H20JYEK/AQgB47okPMKM8Aig7N+NVg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":1747710,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc71clCRA9TVsSAnZWagAAACMP/An4EwQ6kX5IhSMOcOCs\nqbWIVZefqTT0HG2ZXmr4brO5Dj53iWMi8se15bfMzubVAJMVPdg8BF2p+zke\nLVQGMi63Cav2SO075wGqNbOtHYuPCxCVslOIeAK+3ZTwdW8mPmt4kX/N1blj\nQ0Ae2SRTX/e2RX7p8/JEg3Sw+WO7l3B+QgvYe0vttU2huk9N6DL7YiqgASmn\npULtVu9G29IiNw7fEicRVUw6HZMWlF7epaiHfwvWFCOnNY+A+0RbYpUiWn4f\nKYD8zvgpai83aBKhgFhfO1JUsCfiuddqjK4LbAhJ/64R/L9rR57ewD2muTPG\nRIPCKA5ouBaR/54CETugpjdHHzG1VyuF3d2CS4D4IgKg/0w46mzQORGyqusx\no6rcAsq+T7Dw1LDoXSFZozHrCSy3yoMmnwKFXp7LiuD6nfOsHuiUO8SMt0XF\neSUPXNfHuM6q4pudIwDEjoH4PteeiE7doEuatp0mNEQbC/pnYhFwfhVG5MrM\n4VlPQakZXrr48HNWCwg8wTYd/uwmnZ0LtD1g/VCvUgABDU6JVG3E3SYmY3OX\nZzq2hiVMrz63T5Xd7f0r93m+2ZdpQL4b3x3+QA05gMoNovTvjIlYZT5x5486\nWaD4aElHBbjGZ+zuTnngrV2qjXtinNqKLR9FJrJAjPCwNMO+tIJlGtpafBC+\nE5G7\r\n=OT+4\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"sobear","email":"sobear.me@gmail.com"},"_npmVersion":"5.6.0","description":"Example component","directories":{},"_nodeVersion":"8.11.1","dependencies":{"prop-types":"^15.5.8","lodash.find":"^4.6.0","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"componentConfig":{"name":"ice-form","title":"Example component","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.14.4","ice-scripts":"^2.0.0","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.2","ice-plugin-fusion":"^0.1.4","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.1","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.0-2_1559189284891_0.36323368066787265","host":"s3://npm-registry-packages"}},"0.1.0-3":{"name":"@ice/form","version":"0.1.0-3","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.0-3","maintainers":[{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.0-3/build/index.html","dist":{"shasum":"5ba4d32561fbe5123e1f05aa7f667eefcb12d4ba","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.0-3.tgz","fileCount":30,"integrity":"sha512-2sOjt4GTL2LVFdt5fhO1bYmXewgr4ZixLcpIgeiL9FOxcf94rdlyrRdhquvlW+1S7K0NtObqp1BIiPepkX2JQA==","signatures":[{"sig":"MEQCIAQnaaDbHlN6Fg0BUg9m6QU2/YVzwWb5oMvG570Jqop3AiAk3iNL7x4+qR0o4m4v1uFVGyIE3VRzkSbs8h+yn5wGow==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2671146,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9OtfCRA9TVsSAnZWagAAi4EQAJehUp0kuKkhcIX9JvU7\nsNBeeO78Das/EMgSN9PhODM5tS9tTj23CGI3gJAPjuvnGQCvgHtdAmXD1FpZ\nLl8KdOgrpwdoKI1rGcD9QjO10hBHHpfGH94giC9/adsIKdJMnLlXGjkkfCiv\nFtZlGY+b4F/NATNey+CrZBhK9m+vr54sEDaQGbz9JPWTy91iZhi9yl+nxB9h\n3QZp8kHa/RoOvW5a75YkGA4Vjc3x8YbtAJsa+mabAhkkUqyGWG4H/razEGLq\nrQhinezPXa77d9cAcTl0Kk9dFZWpQWGsFweyZ7/xOl7fSUv1LgW4HrXcsWYH\nk9Peti2YAIfFDJnFl20fdSZMvc6eUuOq+H96T3fN188aBAPY/mYcw+2ntb4O\nUFhZYyCkCvNI6Nyss2IYI9VqcE582+6567L5LbS9ANdzuwfAAHo+YcdDK3Xw\ntl7Hwvtv2l2bPOPbphvIaGPkg0a3mrKkKxzW+shHBiQxmhMKteHL87OY/N2q\nbqEq3+b21I/6bJwXJpjXpccroUvc9zAIy2ERfJEo0tm9SUVC6sFoQOGGF0Ea\nHZoYgmhxrbqQKC4LHTCP0kMreY4VElEjosRPjep7eL0NPEsSaanzlDvGERkW\nZ+FPdfNlAWfsdMHwSCRdB9K8hw1EV9cbsqXeEdsfU28XHdHIUepKlUs3ekiB\naN5I\r\n=NTc0\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"## 背景\n\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n## 特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n## 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时需要重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n## 为什么不？\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n## 安装\n\n```bash\n$ npm i @ice/form --save\n```\n\n## 快速上手\n\n下面例子演示了如何创建一个简单的 form：\n\n```js\nimport React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Form, Field } from '@ice/form';\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nclass App extends Component {\n  async onSubmit(values) {\n    await sleep(300)\n    window.alert(JSON.stringify(values, 0, 2))\n  }\n\n  render() {\n    return (\n      <div>\n        <Form onSubmit={this.onSubmit}>\n          <div>Simple Form</div>\n          <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n          <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n          <Field label=\"爱好：\" name=\"hobby\" component='select'>\n            <option value=\"\">--Please choose an option--</option>\n            <option value=\"basketball\">篮球</option>\n            <option value=\"football\">足球</option>\n            <option value=\"badminton\">羽毛球</option>\n          </Field>\n          <button type=\"submit\">Submit</button>\n        </Form>\n      </div>\n    );\n  }\n}\n\nReactDOM.render((\n  <App />\n), mountNode);\n```\n\n## Form 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| linkages |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n```js\n// layout\n{\n  labelAlign: 'left', // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right', // label 文字左对齐右对齐，默认 'right' 右对齐\n  labelCol: 1, // label 占的栅格宽度，共 6 等分，默认 1\n  wrapperCol: 3, // 输入控件占的栅格宽度，共 6 等分，默认 3\n  tipsCol: 1 // 提示信息占的栅格宽度，共 6 等分，默认 1\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`linkages` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  linkages={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n数组的每一项是个对象，对象的 `field` 表示监听哪一个 `Field`，`handler` 函数是处理联动逻辑，监听 `field` 的 `onChange` 事件，然后设置其他表单项的数据，进而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string 或者 React Element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |     |    -    | 'input' 'textarea' Input Radio   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| linkages |  联动规则   |  N    |   object   |    -    |   -   |\n| display |  显示隐藏   |  N    |   string   |    |   'show' / 'hide'  |\n| format |  格式化 value  |  N    |   function   |    |  function(value) => formatValue  |\n| fieldLayout |  设置当前 Field 的布局   |  N    |   object   |   同 layout   |  Field 的 fieldLayout 设置会覆盖 layout 设置|\n| tips |  提示信息   |  N    |   string   |    |    |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方表单 onChange 的第一个参数不是 event 或者 value，用户可以主动设置对应的值。比如，接入表单的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)`  |\n\n其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n`Field` 的 `rules` 和 `linkages` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" linkages={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {display: 'show'});\n      } else {\n        formCore.setFieldProps('age', {display: 'hide'});\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" status=\"hide\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据。\n\n- `getFieldValue(name)`\n  获取某一 `Field` 的值\n- `getValues()`\n  获取表单的 values\n- `setFieldValue(name, value)`\n  设置某一 `Field` 的值\n- `setValues(values)`\n  设置某些 `Field` 的值\n- `getFieldError(name)`\n  获取某一 `Field` 的 error 信息\n- `getErrors()`\n  获取表单的 errors\n- `setFieldError(name, errMsg)`\n  设置某一 `Field` 的 error 信息\n- `setErrors(errors)`\n  设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`\n  获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`\n  设置某一 `Field` 的属性值\n- `submit()`\n  提交表单\n- `reset()`\n  重置表单\n\n也可以通过属性的方式获取到一些数据：\n- `formCore.values`\n  获取表单的所有值\n- `formCore.errors`\n  获取表单校验的错误信息\n- `formCore.pristine`\n  表单当前的 `values` 是否与 `initialValues` 相等\n\n## 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)\n","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"sobear","email":"sobear.me@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.11.1","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.0-3_1559554910710_0.13700225367124275","host":"s3://npm-registry-packages"}},"0.1.0-4":{"name":"@ice/form","version":"0.1.0-4","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.0-4","maintainers":[{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.0-4/build/index.html","dist":{"shasum":"a6e1711ac97fc9c911c3e0529f65a86537727f72","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.0-4.tgz","fileCount":30,"integrity":"sha512-PpNnLE8EH2dAWZmuXw5ZqckklhP7JtAjv7xjVKWMs2Nbci+xkHWbkpS33c0AzQmNsSK70F+ipsoDMwsD2GJpxQ==","signatures":[{"sig":"MEUCIFHnyEjiDAeOpqwhctlAsSofThXJirJt5hzm7qcWahHiAiEA6xk9DjkojNG3EqYUHIN9Q60S/wXoL/99B8C3VP3XeHQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2673829,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9O4PCRA9TVsSAnZWagAA0NYQAINtbPr+/rSlRO9KgF0y\n/X1uXaWVB7ISTpCvomPdin1y4PabhGWI2DUinTm3H3WRnzyYpKwTM6vcAg4l\nM29P70297jlOyhenhK/TRB+SwATp4veNsLXY7J0nLVDa1l/gdyczr91597QS\nUnlwjhgtnUPJZ9t36ilCCVAHLvFy9OM+s+FB9TYcgyEGyqKNzxdW10Wag9E2\nXotn9V3Vi38raGkbErSTzStnN1cZadAd+bOnFU83Man/KokgaCrBFNKahYIS\nLc8gcN4pD2sp7gsGGr63GZXnLyiQ3kZnK3ojPPeh9a6obcCgOptebXclHkpb\nX8yKGs66xAIjupe1F8470gD9jdapcCdyWkQRbLyFWBPYAHM6xlic0GISw5ho\n4u6iRM8E/kpeaRrtuKBN6CLDzhxk1N2hQgFFFvxjQrqEiy8Z8yq1vdfLj/61\noIOZyPKq49tWDA6VTnwZzEfhBdM7fv0e18BMST5Dsz9NVWWzfuPv1xLVT404\nMC5m26pHkNY9fVcpdFn8KBo/oUcVb4ED1aAD5ldzD2fclTjwbTKDgQJ4/No7\nZtDFNd6ZsQNoRRsXAv8CdmiC6s/lhkvT+AWx2akeUgOgGw4Pv8SU0VveAp/E\ni1YzLQ3DDlN2SnLnwsem/aZXvhZFleNZwAXNq5uuEJwypVhVeOP9z/Tna2Oz\npX2j\r\n=F31N\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"## 背景\n\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n## 特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n## 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时需要重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n## 为什么不？\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n## 安装\n\n```bash\n$ npm i @ice/form --save\n```\n\n## 快速上手\n\n下面例子演示了如何创建一个简单的 form：\n\n```js\nimport React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Form, Field } from '@ice/form';\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nclass App extends Component {\n  async onSubmit(values) {\n    await sleep(300)\n    window.alert(JSON.stringify(values, 0, 2))\n  }\n\n  render() {\n    return (\n      <div>\n        <Form onSubmit={this.onSubmit}>\n          <div>Simple Form</div>\n          <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n          <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n          <Field label=\"爱好：\" name=\"hobby\" component='select'>\n            <option value=\"\">--Please choose an option--</option>\n            <option value=\"basketball\">篮球</option>\n            <option value=\"football\">足球</option>\n            <option value=\"badminton\">羽毛球</option>\n          </Field>\n          <button type=\"submit\">Submit</button>\n        </Form>\n      </div>\n    );\n  }\n}\n\nReactDOM.render((\n  <App />\n), mountNode);\n```\n\n## Form 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| linkages |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n```js\n// layout\n{\n  labelAlign: 'left', // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right', // label 文字左对齐右对齐，默认 'right' 右对齐\n  labelCol: 1, // label 占的栅格宽度，共 6 等分，默认 1\n  wrapperCol: 3, // 输入控件占的栅格宽度，共 6 等分，默认 3\n  tipsCol: 1 // 提示信息占的栅格宽度，共 6 等分，默认 1\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`linkages` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  linkages={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n数组的每一项是个对象，对象的 `field` 表示监听哪一个 `Field`，`handler` 函数是处理联动逻辑，监听 `field` 的 `onChange` 事件，然后设置其他表单项的数据，进而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string 或者 React Element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |     |    -    | 'input' 'textarea' Input Radio   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| linkages |  联动规则   |  N    |   object   |    -    |   -   |\n| display |  显示隐藏   |  N    |   string   |    |   'show' / 'hide'  |\n| format |  格式化 value  |  N    |   function   |    |  function(value) => formatValue  |\n| fieldLayout |  设置当前 Field 的布局   |  N    |   object   |   同 layout   |  Field 的 fieldLayout 设置会覆盖 layout 设置|\n| tips |  提示信息   |  N    |   string   |    |    |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方表单 onChange 的第一个参数不是 event 或者 value，用户可以主动设置对应的值。比如，接入表单的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)`  |\n\n其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n`Field` 的 `rules` 和 `linkages` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" linkages={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {display: 'show'});\n      } else {\n        formCore.setFieldProps('age', {display: 'hide'});\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" status=\"hide\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据。\n\n- `getFieldValue(name)`\n  获取某一 `Field` 的值\n- `getValues()`\n  获取表单的 values\n- `setFieldValue(name, value)`\n  设置某一 `Field` 的值\n- `setValues(values)`\n  设置某些 `Field` 的值\n- `getFieldError(name)`\n  获取某一 `Field` 的 error 信息\n- `getErrors()`\n  获取表单的 errors\n- `setFieldError(name, errMsg)`\n  设置某一 `Field` 的 error 信息\n- `setErrors(errors)`\n  设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`\n  获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`\n  设置某一 `Field` 的属性值\n- `submit()`\n  提交表单\n- `reset()`\n  重置表单\n\n也可以通过属性的方式获取到一些数据：\n- `formCore.values`\n  获取表单的所有值\n- `formCore.errors`\n  获取表单校验的错误信息\n- `formCore.pristine`\n  表单当前的 `values` 是否与 `initialValues` 相等\n\n## 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)\n","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.0-4_1559555598752_0.6251053410584493","host":"s3://npm-registry-packages"}},"0.1.0-5":{"name":"@ice/form","version":"0.1.0-5","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.0-5","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.0-4/build/index.html","dist":{"shasum":"91227f20681826ff297f07f178f07d1cb02d24fd","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.0-5.tgz","fileCount":34,"integrity":"sha512-kCpQsa2H+oYq5qqbiV0DlZ5KleFcLBA8W1dioIlJtLe5CAMiFzWxWYbpbiHwfyJ/29BFjLdVm4WES45lzZCDsg==","signatures":[{"sig":"MEUCIEontWaLaP0h5+6KiV9GC9Xnz8J+07tKY1UT+7EyFLjOAiEAq5LW9teljKQJbCX2IKyWjSxNbbJBeQmh82UvR7NsqY4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":78390,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc+KofCRA9TVsSAnZWagAAsV4P/3ML2/eRdfursY2tRAWf\nNnPKaNY72gArbsJHngzdSLik4fLE6oQMCKX7zoCyDQ5+WiHw7zHMO3nw39Db\nKLYhUJZdlnKCFFmPdrtKMjYzQGdgKUjh+xwEDc4vFH9cfDpfp6PfsGb/cdIW\nb0/v9OKQa5I0fCwkg6/hxX+FTr97+qum72hm+75LtwKoD1B0BFKNSe4fhupQ\n51Tu6tNddaUo+e6D9XZJGECDSObralzVjzBy395DyRJUgCLgyonQe0D6QN1H\nD+tVBAIlqP3mu8PJH9nupJvcMUZhe6BLE/PkzN+k+ty6lHQpyIb9h/RzG1RJ\n+b1+0LFywtCNwmpsRUlC3E7imxbrp6jRv5gFjtGkx9zPYYhJCSgE2KWolLCM\n5PD6pxp6dOcCtn1ZyIb0PFSiGZaWgwXBpvCTyAniHaqVqJOwhjNPRCff8i+J\nmK8v/Rdo7ZtVIWisgpgYA5J14rXWg+TR4w9bDnocdVLAxURJM3D/kw1B/rx/\nfgdfT8+6OwIfWMqwMYkYl39vngItfP3qfn1QjcqciyGn5mTDUpgr3ikvHJyT\nL7yZ7UYbC2mHJJ1E5FtCuLBz4t0/lNOpBXxjFdXoiiyhTgn6FovdcJCw3Qgq\n/4EPNqI9f0PTp15dL1VZQN4aVfPG+diDHdy82w4N59gHo81GIG+NiRL5B4E6\nSERj\r\n=Wxm8\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"## 背景\n\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n## 特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n## 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时需要重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n## 为什么不？\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n## 安装\n\n```bash\n$ npm i @ice/form --save\n```\n\n## 快速上手\n\n下面例子演示了如何创建一个简单的 form：\n\n```js\nimport React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Form, Field } from '@ice/form';\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nclass App extends Component {\n  async onSubmit(values) {\n    await sleep(300)\n    window.alert(JSON.stringify(values, 0, 2))\n  }\n\n  render() {\n    return (\n      <div>\n        <Form onSubmit={this.onSubmit}>\n          <div>Simple Form</div>\n          <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n          <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n          <Field label=\"爱好：\" name=\"hobby\" component='select'>\n            <option value=\"\">--Please choose an option--</option>\n            <option value=\"basketball\">篮球</option>\n            <option value=\"football\">足球</option>\n            <option value=\"badminton\">羽毛球</option>\n          </Field>\n          <button type=\"submit\">Submit</button>\n        </Form>\n      </div>\n    );\n  }\n}\n\nReactDOM.render((\n  <App />\n), mountNode);\n```\n\n## Form 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| effects |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n```js\n// layout\n{\n  labelAlign: 'left', // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right', // label 文字左对齐右对齐，默认 'right' 右对齐\n  labelCol: 1, // label 占的栅格宽度，共 6 等分，默认 1\n  wrapperCol: 3, // 输入控件占的栅格宽度，共 6 等分，默认 3\n  tipsCol: 1 // 提示信息占的栅格宽度，共 6 等分，默认 1\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`effects` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  effects={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n数组的每一项是个对象，对象的 `field` 表示监听哪一个 `Field`，`handler` 函数是处理联动逻辑，监听 `field` 的 `onChange` 事件，然后设置其他表单项的数据，进而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string 或者 React Element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |     |    -    | 'input' 'textarea' Input Radio   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| effects |  联动规则   |  N    |   object   |    -    |   -   |\n| display |  显示隐藏   |  N    |   string   |    |   'show' / 'hide'  |\n| format |  格式化 value  |  N    |   function   |    |  function(value) => formatValue  |\n| layout |  设置当前 Field 的布局   |  N    |   object   |   同 layout   |  Field 的 layout 设置会覆盖 layout 设置|\n| tips |  提示信息   |  N    |   string   |    |    |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方表单 onChange 的第一个参数不是 event 或者 value，用户可以主动设置对应的值。比如，接入表单的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)`  |\n\n其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n`Field` 的 `rules` 和 `effects` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" effects={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {display: 'show'});\n      } else {\n        formCore.setFieldProps('age', {display: 'hide'});\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" status=\"hide\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据。\n\n- `getFieldValue(name)`\n  获取某一 `Field` 的值\n- `getValues()`\n  获取表单的 values\n- `setFieldValue(name, value)`\n  设置某一 `Field` 的值\n- `setValues(values)`\n  设置某些 `Field` 的值\n- `getFieldError(name)`\n  获取某一 `Field` 的 error 信息\n- `getErrors()`\n  获取表单的 errors\n- `setFieldError(name, errMsg)`\n  设置某一 `Field` 的 error 信息\n- `setErrors(errors)`\n  设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`\n  获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`\n  设置某一 `Field` 的属性值\n- `submit()`\n  提交表单\n- `reset()`\n  重置表单\n\n也可以通过属性的方式获取到一些数据：\n- `formCore.values`\n  获取表单的所有值\n- `formCore.errors`\n  获取表单校验的错误信息\n- `formCore.pristine`\n  表单当前的 `values` 是否与 `initialValues` 相等\n\n## 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)\n","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.0-5_1559800350965_0.20333014543226624","host":"s3://npm-registry-packages"}},"0.1.0-6":{"name":"@ice/form","version":"0.1.0-6","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.0-6","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.0-6/build/index.html","dist":{"shasum":"41cfe261564f29c1b8250870cb638096a0b670bf","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.0-6.tgz","fileCount":37,"integrity":"sha512-KaW4hZ5/5+92cM3+l4WE4PmP4md2rSbXgKESX9bOdgQh4Pc/AoedhNoQDG3f97/9cr81Zi44rmanWFZ+4r2ukA==","signatures":[{"sig":"MEUCIQDAlW6FIRG5sq9ynI95Q0VqzULLHQ6Ilaspl4QE6HnCcwIgLllirOh8phpU/q4mI4cfX9bSAqy2fnHdAdNSH0ywkmI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2818792,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc+LeYCRA9TVsSAnZWagAAV7gP/i3fzpA86OgbhAd5bSKG\n8YktzlXhNe35DWUHLkpBxgsy7kGu1o3azv8PqVxq7t519rBojTOwdaRCjnVz\nAZRuo/bgCXPEU7LfX9UL6n0Cl8w9tmh/lyCNktKzWByxn26/H2GUFFCVUck8\nNaHbnjZkjbDRO5wjwjxsRe8RZ2b+Zv+5MY/Z3WbKwwdaDG90weMph6gmwnLp\nFYfJCR/ptvF4x8QFjeEgUo7zQlu/FDkMVQSBvK7uJFixIN8jjbPnsSAjccN5\nb5VQ6ofz/oHzy7DSi48XJUUESbPRXk9+GrrCb72GXZFKBl6h8BRSG2WwH8D1\n9HHW2uj3wexfamwRa/35qdrhh4QnDZUE2A3Qy0kylKvYjhFpv8XZBnjVLAka\nAZI7CTQWHpRyTS/+txRZ+5GaC/HkfanJBRE6jHQMan1uIhzMD7RLyu1sbgzi\n/9DaEWZV7HVT8xlxXUk7AbgOLn/hTsy4/CagSMdtuYAsiKKLoHWqZaOW0TuW\nXmJ9xPjdQ02eeerc/Sx6y9nLf0/HeOMPmHFIaFVW15xUplY4KRApkEAWMvBi\n/3nF5C05t23n48PEGFbaoSGpARAV4Fl7zhvHbHLPlm4kfbsVgGkUMTqTj+AK\ncICTOcOdeHdLBcsc2lvYKRP4mx1QjRL6WeVsinrGN+u50zXOwEdC8xF3yoEJ\n0v6N\r\n=fClf\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"## 背景\n\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n## 特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n## 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时需要重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n## 为什么不？\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n## 安装\n\n```bash\n$ npm i @ice/form --save\n```\n\n## 快速上手\n\n下面例子演示了如何创建一个简单的 form：\n\n```js\nimport React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Form, Field } from '@ice/form';\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nclass App extends Component {\n  async onSubmit(values) {\n    await sleep(300)\n    window.alert(JSON.stringify(values, 0, 2))\n  }\n\n  render() {\n    return (\n      <div>\n        <Form onSubmit={this.onSubmit}>\n          <div>Simple Form</div>\n          <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n          <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n          <Field label=\"爱好：\" name=\"hobby\" component='select'>\n            <option value=\"\">--Please choose an option--</option>\n            <option value=\"basketball\">篮球</option>\n            <option value=\"football\">足球</option>\n            <option value=\"badminton\">羽毛球</option>\n          </Field>\n          <button type=\"submit\">Submit</button>\n        </Form>\n      </div>\n    );\n  }\n}\n\nReactDOM.render((\n  <App />\n), mountNode);\n```\n\n## Form 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| effects |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n```js\n// layout\n{\n  labelAlign: 'left', // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right', // label 文字左对齐右对齐，默认 'right' 右对齐\n  labelCol: 1, // label 占的栅格宽度，共 6 等分，默认 1\n  wrapperCol: 3, // 输入控件占的栅格宽度，共 6 等分，默认 3\n  tipsCol: 1 // 提示信息占的栅格宽度，共 6 等分，默认 1\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`effects` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  effects={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n数组的每一项是个对象，对象的 `field` 表示监听哪一个 `Field`，`handler` 函数是处理联动逻辑，监听 `field` 的 `onChange` 事件，然后设置其他表单项的数据，进而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string 或者 React Element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |     |    -    | 'input' 'textarea' Input Radio   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| effects |  联动规则   |  N    |   object   |    -    |   -   |\n| display |  显示隐藏   |  N    |   string   |    |   'show' / 'hide'  |\n| format |  格式化 value  |  N    |   function   |    |  function(value) => formatValue  |\n| layout |  设置当前 Field 的布局   |  N    |   object   |   同 layout   |  Field 的 layout 设置会覆盖 layout 设置|\n| tips |  提示信息   |  N    |   string   |    |    |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方表单 onChange 的第一个参数不是 event 或者 value，用户可以主动设置对应的值。比如，接入表单的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)`  |\n\n其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n`Field` 的 `rules` 和 `effects` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" effects={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {display: 'show'});\n      } else {\n        formCore.setFieldProps('age', {display: 'hide'});\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" status=\"hide\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据。\n\n- `getFieldValue(name)`\n  获取某一 `Field` 的值\n- `getValues()`\n  获取表单的 values\n- `setFieldValue(name, value)`\n  设置某一 `Field` 的值\n- `setValues(values)`\n  设置某些 `Field` 的值\n- `getFieldError(name)`\n  获取某一 `Field` 的 error 信息\n- `getErrors()`\n  获取表单的 errors\n- `setFieldError(name, errMsg)`\n  设置某一 `Field` 的 error 信息\n- `setErrors(errors)`\n  设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`\n  获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`\n  设置某一 `Field` 的属性值\n- `submit()`\n  提交表单\n- `reset()`\n  重置表单\n\n也可以通过属性的方式获取到一些数据：\n- `formCore.values`\n  获取表单的所有值\n- `formCore.errors`\n  获取表单校验的错误信息\n- `formCore.pristine`\n  表单当前的 `values` 是否与 `initialValues` 相等\n\n## 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)\n","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.0-6_1559803799733_0.6177595710695454","host":"s3://npm-registry-packages"}},"0.1.0-7":{"name":"@ice/form","version":"0.1.0-7","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.0-7","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.0-7/build/index.html","dist":{"shasum":"456c9f95f0f58561f5fa79fec67a2a3efc27b3a1","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.0-7.tgz","fileCount":37,"integrity":"sha512-Yj/IeXhlIVV69R28j1ZA3rCWXRdjpr2D7ZO0qPxuKvU3JGlfuQkVtt8kXeqTL0AOZD7CVXQ/I0jM/8BEDmfVJQ==","signatures":[{"sig":"MEQCIGhbt+DUp4P/mMpnXapfAsfiR5f/Sn6/LbY+dphL9LseAiBOJdG/en08GnwXJWGR5dSCJDfqwuu+AvXQVNMfXegXJA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2819488,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc+MESCRA9TVsSAnZWagAAs6UP/3r/oJlkHQHkjICpbkPk\nm/QSWmgTYeL6uViwEhNxkuzDH3gExoaOJJEizWO8HGqYmCB3aB5s0aOfH9u0\nwQxf32MSMDU19YQjAMKiuGZkWFw/RxqW/n2AtFXP5joNtR0MNDQSpTYWdNf6\n0JqXqyn3q6F0LUM4k1ddFZGNuOUvNNhwKvFGepr/LpJmI7YNcOgsuLjj8e3e\nHdfxoIcOvtkLRG9Z176wirt6LDXRoIZFarHa8xo0RGL0AGWrnGgU9ESYNhli\n1G32xV4oKgFiuySKEDlLw2sBRM/DbCU4OlusVPEce0/zqq9Gsgp0Mu8OoJNV\nK6raeAsOrNcQ/bJidcC+LUJGx5I/JzQkyYZNK8Ltte1r1Coxz1KD+0aRx3OJ\n0c+aqQ5NYAs2g91y4IYSfva9pHxq0ob4h6dXCJpyKcfI5PeqrDe0lQh5ypso\nj4v2rXkaNbwPrRQ/lDxKiNWfjATKN9dQfSwvJAkc90X9nQBT9tUYq7ikuFDU\nT874hNdZvY407aKWAF803Qmlji8xSGuAjRN0wBAwyAs4WoGbHMGrVnpAG53B\ngsCTqkOjreBIP+AssA2Sus0IYCYCCjK0wuCGKOtOe0DjnLbHp+vnK7MjAbJU\nUP5X70iOwN7ZxIdgIwPhBi7sLO5rXh6NgyzZOoKLH5ty16GcCoNgqb/koOQz\nWOga\r\n=tcPm\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"## 背景\n\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n## 特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n## 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时需要重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n## 为什么不？\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n## 安装\n\n```bash\n$ npm i @ice/form --save\n```\n\n## 快速上手\n\n下面例子演示了如何创建一个简单的 form：\n\n```js\nimport React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Form, Field } from '@ice/form';\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nclass App extends Component {\n  async onSubmit(values) {\n    await sleep(300)\n    window.alert(JSON.stringify(values, 0, 2))\n  }\n\n  render() {\n    return (\n      <div>\n        <Form onSubmit={this.onSubmit}>\n          <div>Simple Form</div>\n          <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n          <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n          <Field label=\"爱好：\" name=\"hobby\" component='select'>\n            <option value=\"\">--Please choose an option--</option>\n            <option value=\"basketball\">篮球</option>\n            <option value=\"football\">足球</option>\n            <option value=\"badminton\">羽毛球</option>\n          </Field>\n          <button type=\"submit\">Submit</button>\n        </Form>\n      </div>\n    );\n  }\n}\n\nReactDOM.render((\n  <App />\n), mountNode);\n```\n\n## Form 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| effects |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n```js\n// layout\n{\n  labelAlign: 'left', // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right', // label 文字左对齐右对齐，默认 'right' 右对齐\n  labelCol: 1, // label 占的栅格宽度，共 6 等分，默认 1\n  wrapperCol: 3, // 输入控件占的栅格宽度，共 6 等分，默认 3\n  tipsCol: 1 // 提示信息占的栅格宽度，共 6 等分，默认 1\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`effects` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  effects={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n数组的每一项是个对象，对象的 `field` 表示监听哪一个 `Field`，`handler` 函数是处理联动逻辑，监听 `field` 的 `onChange` 事件，然后设置其他表单项的数据，进而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string 或者 React Element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |     |    -    | 'input' 'textarea' Input Radio   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| effects |  联动规则   |  N    |   object   |    -    |   -   |\n| display |  显示隐藏   |  N    |   string   |    |   'show' / 'hide'  |\n| format |  格式化 value  |  N    |   function   |    |  function(value) => formatValue  |\n| layout |  设置当前 Field 的布局   |  N    |   object   |   同 layout   |  Field 的 layout 设置会覆盖 layout 设置|\n| tips |  提示信息   |  N    |   string   |    |    |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方表单 onChange 的第一个参数不是 event 或者 value，用户可以主动设置对应的值。比如，接入表单的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)`  |\n\n其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n`Field` 的 `rules` 和 `effects` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" effects={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {display: 'show'});\n      } else {\n        formCore.setFieldProps('age', {display: 'hide'});\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" status=\"hide\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据。\n\n- `getFieldValue(name)`\n  获取某一 `Field` 的值\n- `getValues()`\n  获取表单的 values\n- `setFieldValue(name, value)`\n  设置某一 `Field` 的值\n- `setValues(values)`\n  设置某些 `Field` 的值\n- `getFieldError(name)`\n  获取某一 `Field` 的 error 信息\n- `getErrors()`\n  获取表单的 errors\n- `setFieldError(name, errMsg)`\n  设置某一 `Field` 的 error 信息\n- `setErrors(errors)`\n  设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`\n  获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`\n  设置某一 `Field` 的属性值\n- `submit()`\n  提交表单\n- `reset()`\n  重置表单\n\n也可以通过属性的方式获取到一些数据：\n- `formCore.values`\n  获取表单的所有值\n- `formCore.errors`\n  获取表单校验的错误信息\n- `formCore.pristine`\n  表单当前的 `values` 是否与 `initialValues` 相等\n\n## 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)\n","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.0-7_1559806226152_0.9183894007027003","host":"s3://npm-registry-packages"}},"0.1.0-8":{"name":"@ice/form","version":"0.1.0-8","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.0-8","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.0-8/build/index.html","dist":{"shasum":"6dbc7b2f661bc5ad1a8e1b75ecf7c1e9a5f71061","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.0-8.tgz","fileCount":35,"integrity":"sha512-HxM/2tdtl8KETp6YTZMLe9MFMU89yXnRlzIsks0TlWpcb/PS1SG2avJdKPfZrtfpguhpPYl/z9iLfpj4HpEpjg==","signatures":[{"sig":"MEUCIQCofpYEaguEEQkB6ZQR1eRjy14ei/0ApkKpB6iQhuXTjgIgdJSBmsKBnEWeXZM9p3WBgHe8kGZSMQK5eLpMHrI4ivU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2822230,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc+MUWCRA9TVsSAnZWagAA1jMP/jxhpszZt9Rd+RBFDo3d\nqf/b4XS7po7t1HTk6oZRut0Q5o95Ht6eQgFPojUhI8zjUXRvzwj8lSYT8Cmh\n5WbElmfwN2qoI2B7RObMHj7FhIwUAGWdJkuvpsBrsftQcNCDBja2aH+WmSf+\n31le9tBBupQrugBGehcIW5CfA085KO03WlJctPbUpJAwYYOG0IiEaXk+pARN\nzPxJoGvQ0V2Qfo7JzzhHnHxz1MS6yXZ7h7PJHE6swgEG3CLYNLOgYTj/V85/\nEmDwNKs9cDcyysNt073HChgFBzLc65t94OpI3/wsh2UHMJRwPkryPgT6MMKL\nyly/Mo8WBwyKy5bW/w0fIoXmY0wEgjgFCWgDcuxfUQ6WbFJx1/DBhTE5U0D2\nkORNdGWsfkxM3ntWLLys/UAOOsW8jPfZMcJ5trc3g4EQz0IZ/p2LArpzHWta\nACPwpOG1ivQaQ/5nwn55R67yHszmiRaP0IDvV4Nsri6bmovhjBoPRkTv9Lx8\nJAX+7z5Pau4rl+4z2jwBOmlEriEY6LrvhIga6mmqwan5/Oiuz+ELA+rggOow\nPHpSICJ/P1KX53CJ6L5m/OTC5LblUJJV9vaAhbKUOsOW6LNRU8kyk1fUMahi\nmU9iwNQKQ6TJR/6TBeOIibNOYxpJamoerH1P7QrAOFM/peY8jvUBA2XCa2wd\nAlFX\r\n=esRo\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"## 背景\n\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n## 特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n## 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时需要重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n## 为什么不？\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n## 安装\n\n```bash\n$ npm i @ice/form --save\n```\n\n## 快速上手\n\n下面例子演示了如何创建一个简单的 form：\n\n```js\nimport React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Form, Field } from '@ice/form';\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nclass App extends Component {\n  async onSubmit(values) {\n    await sleep(300)\n    window.alert(JSON.stringify(values, 0, 2))\n  }\n\n  render() {\n    return (\n      <div>\n        <Form onSubmit={this.onSubmit}>\n          <div>Simple Form</div>\n          <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n          <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n          <Field label=\"爱好：\" name=\"hobby\" component='select'>\n            <option value=\"\">--Please choose an option--</option>\n            <option value=\"basketball\">篮球</option>\n            <option value=\"football\">足球</option>\n            <option value=\"badminton\">羽毛球</option>\n          </Field>\n          <button type=\"submit\">Submit</button>\n        </Form>\n      </div>\n    );\n  }\n}\n\nReactDOM.render((\n  <App />\n), mountNode);\n```\n\n## Form 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| effects |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n```js\n// layout\n{\n  labelAlign: 'left', // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right', // label 文字左对齐右对齐，默认 'right' 右对齐\n  labelCol: 1, // label 占的栅格宽度，共 6 等分，默认 1\n  wrapperCol: 3, // 输入控件占的栅格宽度，共 6 等分，默认 3\n  tipsCol: 1 // 提示信息占的栅格宽度，共 6 等分，默认 1\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`effects` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  effects={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n数组的每一项是个对象，对象的 `field` 表示监听哪一个 `Field`，`handler` 函数是处理联动逻辑，监听 `field` 的 `onChange` 事件，然后设置其他表单项的数据，进而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string 或者 React Element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |     |    -    | 'input' 'textarea' Input Radio   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| effects |  联动规则   |  N    |   object   |    -    |   -   |\n| display |  显示隐藏   |  N    |   string   |    |   'show' / 'hide'  |\n| format |  格式化 value  |  N    |   function   |    |  function(value) => formatValue  |\n| layout |  设置当前 Field 的布局   |  N    |   object   |   同 layout   |  Field 的 layout 设置会覆盖 layout 设置|\n| tips |  提示信息   |  N    |   string   |    |    |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方表单 onChange 的第一个参数不是 event 或者 value，用户可以主动设置对应的值。比如，接入表单的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)`  |\n\n其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n`Field` 的 `rules` 和 `effects` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" effects={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {display: 'show'});\n      } else {\n        formCore.setFieldProps('age', {display: 'hide'});\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" status=\"hide\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据。\n\n- `getFieldValue(name)`\n  获取某一 `Field` 的值\n- `getValues()`\n  获取表单的 values\n- `setFieldValue(name, value)`\n  设置某一 `Field` 的值\n- `setValues(values)`\n  设置某些 `Field` 的值\n- `getFieldError(name)`\n  获取某一 `Field` 的 error 信息\n- `getErrors()`\n  获取表单的 errors\n- `setFieldError(name, errMsg)`\n  设置某一 `Field` 的 error 信息\n- `setErrors(errors)`\n  设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`\n  获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`\n  设置某一 `Field` 的属性值\n- `submit()`\n  提交表单\n- `reset()`\n  重置表单\n\n也可以通过属性的方式获取到一些数据：\n- `formCore.values`\n  获取表单的所有值\n- `formCore.errors`\n  获取表单校验的错误信息\n- `formCore.pristine`\n  表单当前的 `values` 是否与 `initialValues` 相等\n\n## 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)\n","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.0-8_1559807253982_0.00514885483666605","host":"s3://npm-registry-packages"}},"0.1.0":{"name":"@ice/form","version":"0.1.0","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.0","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.0/build/index.html","dist":{"shasum":"275ca7665ad39d77ad0b8cd258b74c8005354e97","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.0.tgz","fileCount":35,"integrity":"sha512-nVePFjurkVVpDNTo1WcvBu62wQohK0Ggd4BM5sHxVWK5HLZwwE1GtQnPnYqb2cRRadcvPSKlGZS4NzurGngOKQ==","signatures":[{"sig":"MEUCIF4nHHG86OGvxwTOJHVKU5VFGmqE3D6AHyWRVfuNrDbXAiEAxWcS6+bv+Q2c+zRdZnbddx+XIx+PDLwlvUtdHPEOs+s=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2825122,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc/yBVCRA9TVsSAnZWagAA8KsP/1eUnwUZxDjetx2bATa6\nF9z7G8D5ST0MV/SieXWroKG5cv5JKXp0dj4PovbouFh6N39BsOH5nYLxaBcx\nYsJtZuO1XrUNWSuXN39UldBVhs1FXLszMg+Ne8O44yV4XMwl0v7lww4pXSs0\ndtnswVexoBbE8/uh/re+jM3HRSkZ+boCE6JD+hWtmVELqx0y5oXhMTavAEOV\nvp/ldKnni7ZlolS2fmj/3MWFk3aL3QpwOE771ehD6872PTTyakxc+qTLWAcl\n3rPlzNuNWepW/t4BnKxZzDU/xpEH91BQ3XlxRHAQ/zJHf+Yplck6UaB8veqn\n00Hazg2iVgx16QkwPdAzw5O3jc1klJ1+0pbhdSUVmWU7rLgdWogATqKmeof6\n4DsqWX228gWVVhJ/rAHyA3qw16NyBzm2GlV1cYZtT6vaH0Yn/wJDPGcuzGXw\nczfijX4IenfqEJR6aiAzb/hrqA7SR6Hs/6/2lsK1iUccc6OxAsRaXTxLSAV1\nDJdYf1b8+6vOLJIBKVDLU7xwqmmhsxWprjdgjJNt0f5aR7fZYZP+xfbMqdiG\nRWQZj/BeCPfyK8/FI7xcJw/JXsIldcztNrOL1LWFUkVPE1GWaVROLLQB+38A\nx64whmn35j/4hC/HT/OGbDUx8UAp4/hPwubLX9kwWd+1krQcmQI0SBvPDuwm\nq41q\r\n=mBnW\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.0_1560223828256_0.48091133149058707","host":"s3://npm-registry-packages"}},"0.1.1":{"name":"@ice/form","version":"0.1.1","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.1","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.1/build/index.html","dist":{"shasum":"dc87c1cf86c103299a97fde2c533bcdf262cb9af","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.1.tgz","fileCount":35,"integrity":"sha512-WjU9kFeQFbxMiKnShebmZJ9UCv+dj6wN0LoLA0mAn8hVoWyO77dUk8TX2+elz60+igB7j7cA4+U0MqTjhF317g==","signatures":[{"sig":"MEUCIQD4eaPAZBdhVsmyWa28Epo+oy4mmaE2yB+TZ1lAvac9ewIgAvZFAS2mlqqvQoyTcIi00gugMhkCNHIaqpuGzPt1esw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2826362,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdA2Q1CRA9TVsSAnZWagAAmo4P/2M5Evqzu3nfIBZLIPlB\nUO5Nkeuc2z/3yZlu/YCHDB8XLteMsOdVgj/33oqvxDYTR2pjCtifz12E7iPy\n7hfeOzV1zTEe+MJiMu90ajsX150mwwLygLOj13+H61z5wLxuxV7viwJn/7Nd\nM0H0S3Fo7AdfPE+LJZkauDGhIMS7gHqGDrbBCv/J10ZSEAcyt3knX8Co/8LO\nLdWKspU7bTcZy8QC3HbNZShNlMFwSARUMrf2MvLYi11+PVRbqjs4S0Lxb2Vq\nEpGQZ1eZCf1LBzRfkF7HStgXjF/2cC7SQVS2DrpU8DW14HoNFgj1bxKpdFLF\nwdK7BF7wFWBAqLvy/8Pdyx1hQv4so/YZ8qZbEI3w7OTpn5cm765VohECad/Z\nzuV5Fvzsa0hWhCPMtFb5UjUGP+tq7LCliEwCOVNKMEWv+dVZlF55qFb0NIic\nbgLz9mWhyRW3IjxESkLfQRJAnbHJLoDyCP9QEsumIT5YlXM6i3uDHei+1Pgi\nKqc/ptN9IDngf4imvqFgR3ePiiHmNZlcieNAs3m5qoOmkINIRwbq1sJsQMM0\n/YHdJm8RVeaPHp1CxI84ogZxifAPEjVxrwDHF3fXdeKmrqwz1yV2hOHEwOOK\n8rXQZl3BMOzaTxurVt/ob4E7s7MnzIyz+bjVKQr6WphlPToCunLfwiBDylYC\ng7f9\r\n=A2Lk\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.1_1560503348990_0.9393857344450864","host":"s3://npm-registry-packages"}},"0.1.2-0":{"name":"@ice/form","version":"0.1.2-0","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.2-0","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.2-0/build/index.html","dist":{"shasum":"d01fcc40edfe7b9d3e812d22f5aad1e4ac952267","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.2-0.tgz","fileCount":37,"integrity":"sha512-UPylWNoeMDacdoMQcCir3Fjv1LJOSeHbOtG9y6WrDiKmsHtWQRMLdJmcCFa2C+B+dVxqt0E3XUJl51zmM6jrxg==","signatures":[{"sig":"MEUCIEkxp1U+lkSfAf0QjDvWVC/B5WdaKo67lyNcdJrUGHNqAiEAqrCGcLv8W6VXWujmKdNbTxz2QAxCQWBefG6R6CM96Cs=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2856061,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdDEqCCRA9TVsSAnZWagAAaTEP/3cR0VnTRTkCnZAWBwDz\nPeVjHs65E2fDZhyppizd/z4gCnF1XmpOc7ygafPCW/EJIYPMLGO8aJj7v/gy\nUL2dFBcwAXtOA+TOg9cdAzrrlV0GuW3owukhahii/hs/l04sTiMkwS4ep65Z\njpiQMz3T3CcJpxTCRzqgZvRh+0fTdVpp9Ekb0LIupcEBdRun5ZaBQZr4kr6X\nwMY9eZy+a+t6YVsctSQKnw7TsoslFMDF31Tj1auVpQlRkWWJY+Ne+5yhh3K+\nMckemqqbxtiqXqoKuySkkEYVYaSMk5qe2w8xH8rauRkgtqBF3zFGDUq2ztQf\nzLDEpL1x0hS7zFbpHucNZfKriNvtQIRW2SWW4e7EgUSHw95WowKnDuZ05o7P\nHFp4L98lxcHAKr0aBmeQJxqpxj8Umkh+kyO3yg80o6Iv3Ulj8ZYqSA+dCDdK\np65BUeNI40pFSHvgrtf4U7aUlkmw544I1HBqN+uTMlkHDvorEMuJNorIYKXe\n91JuVCGRxa7ZTMYSgs/Gj07L0bd2biO0svXq4iNLeDCDW79L1XZCn7R8oHoa\n4xY0cRndeFfcGDscfqVe/+0vka8op27jn2XUeDelCIlfR2bkjUSPfq/zGpc5\nAtzPuO1BArDJLU4UAwdQ/1iZFZ7+2t3Z+hr/1p4mrLkRfhzmtjBu/7o9jArA\nO71h\r\n=TaXZ\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"## 安装方法\n\n```bash\n$ npm install @ice/form --save\n```\n\n## 引用方法\n\n```js\nimport { Form, Field, FieldArray } from '@ice/form';\n```\n\n透出 Form、Field、FieldArray 三个组件。\n\n## 快速上手\n\n下面例子演示了如何创建一个简单的 form：\n\n```js\nimport React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Form, Field } from '@ice/form';\nimport { Button, Input } from '@alifd/next';\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nclass App extends Component {\n  async onSubmit(values) {\n    await sleep(300)\n    window.alert(JSON.stringify(values, 0, 2))\n  }\n\n  render() {\n    return (\n      <div>\n        <Form onSubmit={this.onSubmit}>\n          <div>Simple Form</div>\n          <Field label=\"年龄：\" name=\"age\" component={Input} />\n          <Field label=\"年龄：\" name=\"age\" component={Input} htmlType=\"number\" />\n          <Field label=\"简介：\" name=\"intro\" component={Input.TextArea} />\n          <Button htmlType=\"submit\">Submit</Button>\n        </Form>\n      </div>\n    );\n  }\n}\n\nReactDOM.render((\n  <App />\n), mountNode);\n```\n\n## Form 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| onChange |  表单变化回调   |  N    |   function   |    -    |   function(values: object, item: object) => void <br> 参数: <br> values: {object} 表单数据 <br> item: {object} 详细 <br> item.name: {string} 变化的组件名 <br> item.value: {string} 变化的数据 |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| effects |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n| renderField |  自定义 Field 布局   |  N    |   function   |   -   |   function({label, component, error}) => dom  <br> 参数: <br> label: {string/element} Field 的 label <br> component: {string/function} 待渲染的控件 <br> error: {string/element} Field 错误提示信息  |\n\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n`layout` 是个对象，包含 4 个属性：\n```js\n{\n  labelAlign: 'left',       // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right',  // label 文字对齐方式，'left'、'right'，默认 'right'\n  labelCol: 1,             // label 占的栅格宽度，共 6 等分，默认 1\n  wrapperCol: 3,           // 控件占的栅格宽度，共 6 等分，默认 3\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`effects` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  effects={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n监听该 `field` 的 `onChange` 事件，然后设置其他表单项的数据，从而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string/element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |  string/function   |    -    | 'input' 'textarea' Input Radio   |\n| value |  表单项的值    |  N    |  -  |    ''    |   -   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| effects |  联动规则   |  N    |   object   |    -    |   -   |\n| visible |  显示隐藏当前 Field   |  N    |   boolean   |  true  |   true/false  |\n| setValueFormatter |  格式化控件渲染值  |  N    |   function   |    |  function(savedValue) => renderValue  |\n| getValueFormatter |  格式化控件提交值  |  N    |   function   |    |  function(renderValue) => savedValue  |\n| layout |  设置当前 Field 的布局   |  N    |   object   |   同 Form layout   |  当前 Field 的 layout 会覆盖 Form 的 layout |\n| tips |  提示信息   |  N    |   string   |    |    |\n| valueName |  控件值的名称，比如，radio 的 valueName 为 'checked'，value 为 true/false  |  N    |   string   |    |  多用于非常规三方控件  |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方控件 onChange 的第一个参数不是 event 或者 value，可以主动设置对应的值。比如，接入控件的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)` |\n\n`style`、`className` 属性会传递到 Field 最外层 dom 上，其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n\n`Field` 的 `rules` 和 `effects` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" effects={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {\n          visible: true,\n        });\n      } else {\n        formCore.setFieldProps('age', {\n          visible: false,\n        });\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## FieldArray 组件\nFieldArray 表示渲染数组类型的数据，属性同 Field：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n>\n  <FieldArray label=\"新增顾客：\" name=\"customers\">\n    <Field name=\"customer0\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer1\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer2\" component={Input} placeholder=\"customer name\" />\n  </FieldArray>\n  <Field label=\"日期：\" name=\"date\" component={DatePicker} />\n  <Field label=\"\">\n    <Button htmlType=\"submit\">Submit</Button>\n  </Field>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据、状态等。\n\n- `getFieldValue(name)`\n  获取某一 `Field` 的值\n- `setFieldValue(name, value)`\n  设置某一 `Field` 的值\n- `getValues()`\n  获取表单的 values\n- `setValues(values, runEffects)`\n  设置表单的 values，runEffects 为 Boolean，表示设置 values 之后是否需要执行表单的 effects，默认 false\n- `getFieldError(name)`\n  获取某一 `Field` 的 error 信息\n- `setFieldError(name, errMsg)`\n  设置某一 `Field` 的 error 信息\n- `getErrors()`\n  获取所有 `Field` 的 error 信息\n- `setErrors(errors)`\n  设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`\n  获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`\n  设置某一 `Field` 的属性值\n- `submit()`\n  提交表单\n- `reset()`\n  重置表单\n\n也可以通过属性的方式获取到一些数据：\n- `formCore.values`\n  获取表单的所有值\n- `formCore.errors`\n  获取表单校验的错误信息\n- `formCore.pristine`\n  表单当前的 `values` 是否与 `initialValues` 相等\n\n## 延伸阅读\n### 开发 @ice/form 表单背景\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n### 组件特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n### 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n### 竞品对比\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n### 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)\n","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.2-0_1561086593782_0.4900680711081169","host":"s3://npm-registry-packages"}},"0.1.2-1":{"name":"@ice/form","version":"0.1.2-1","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.2-1","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.2-1/build/index.html","dist":{"shasum":"f4263d26e15e3c8c88ba442d4c14bcb9aa2f1072","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.2-1.tgz","fileCount":35,"integrity":"sha512-NZd0NA8xvH384138PsBghTYt/p8YT4vmko6RQcs1sUP9CW20da89HsXGM+Nv/h/XOl/iBxb/PzWTlMK8bhW0HA==","signatures":[{"sig":"MEQCIFuVBFT7/uFxppx7Zuo0VVf+INoMslvnok46vbtzh9FcAiAt5Kpzplyauq0M7CbX//KNe0V/Cex/ScjIBsIs7iy2zw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2826366,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdDKKjCRA9TVsSAnZWagAAOdIP/2oQ+6y9C6gTLX6XqTA/\nEuvdWChLT4Um08/Zq3se5RHeeSTta4K2gL2lr4TjrgKDt6spNb5xhqw/5Jq2\nSAhYEzXhHPaK5YPX2fCGyrNO7IfJZe90bs0vnhRX1NOFmv0qR0v1Vvp2gCw7\nsaol83dTPfZ4uwcXw6eR78U5Ob4s8rYW8LbDapbKVLIzc+6LtC7JYQR8li+R\nkXJBb3YkAM01UfjfrOTHjmtdUi2Tw3nRY5043U5o3dA/eFo5aaG69Yx5PgH9\nRTQdcqvolaKzun70z8ymuQIJiu3VPvJgcHhsG4RPkO2h23orYr6b6fw8k1hG\nirhc6Wg05cBUtkt+FF8+uYAJdAsHC18KcGeVEbKX8uUcaB6dxDQZrIEpRGxX\nu49o7AQ7VVGCYovIxYyfgQElaKUSD+YhvUHSu3oCa30QtEznI+wScQuPFzFF\nRq89QJe7hyNSz/rIw50e+CeadMisNOUa1bw1uI0/pa3F6QOF1ej/jAkrU5NV\n9bMRNlzeJbrKozN4WdCz4IJwpAvQaOlA5Glz3vaNEnBHbN7iZGcL9G5gzWoe\nMm+7Dw/0JeVAeEkp8JhQxk0LX6sBhMeuugb9Vf+OMOTWvDx9CAE+O6wSqCOg\nv0q9C6t5oszD2wd3zWo4BcEoGsvBw0W0N5tARDiMDrby5znckfHlxfvKAq5m\nq7JN\r\n=a5/f\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"## 背景\n\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n## 特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n## 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时需要重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n## 为什么不？\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n## 安装\n\n```bash\n$ npm i @ice/form --save\n```\n\n## 快速上手\n\n下面例子演示了如何创建一个简单的 form：\n\n```js\nimport React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Form, Field } from '@ice/form';\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nclass App extends Component {\n  async onSubmit(values) {\n    await sleep(300)\n    window.alert(JSON.stringify(values, 0, 2))\n  }\n\n  render() {\n    return (\n      <div>\n        <Form onSubmit={this.onSubmit}>\n          <div>Simple Form</div>\n          <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n          <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n          <Field label=\"爱好：\" name=\"hobby\" component='select'>\n            <option value=\"\">--Please choose an option--</option>\n            <option value=\"basketball\">篮球</option>\n            <option value=\"football\">足球</option>\n            <option value=\"badminton\">羽毛球</option>\n          </Field>\n          <button type=\"submit\">Submit</button>\n        </Form>\n      </div>\n    );\n  }\n}\n\nReactDOM.render((\n  <App />\n), mountNode);\n```\n\n## Form 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| onChange |  表单变化回调   |  N    |   function   |    -    |   function(values: Object, item: Object) => void <br> 参数: <br> values: {Object} 表单数据 <br> item: {Object} 详细 <br> item.name: {String} 变化的组件名 <br> item.value: {String} 变化的数据 |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| effects |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n```js\n// layout\n{\n  labelAlign: 'left', // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right', // label 文字左对齐右对齐，默认 'right' 右对齐\n  labelCol: 1, // label 占的栅格宽度，共 6 等分，默认 1\n  wrapperCol: 3, // 输入控件占的栅格宽度，共 6 等分，默认 3\n  tipsCol: 1 // 提示信息占的栅格宽度，共 6 等分，默认 1\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`effects` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  effects={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n数组的每一项是个对象，对象的 `field` 表示监听哪一个 `Field`，`handler` 函数是处理联动逻辑，监听 `field` 的 `onChange` 事件，然后设置其他表单项的数据，进而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string 或者 React Element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |     |    -    | 'input' 'textarea' Input Radio   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| effects |  联动规则   |  N    |   object   |    -    |   -   |\n| visible |  显示隐藏   |  N    |   boolean   |    |   true/false  |\n| format |  格式化 value  |  N    |   function   |    |  function(value) => formatValue  |\n| layout |  设置当前 Field 的布局   |  N    |   object   |   同 layout   |  Field 的 layout 设置会覆盖 layout 设置|\n| tips |  提示信息   |  N    |   string   |    |    |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方表单 onChange 的第一个参数不是 event 或者 value，用户可以主动设置对应的值。比如，接入表单的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)`。手动设置 Field 的 onChange 事件时，若需要监听整个表单变化，则需要主动调用 Form 上的 formCore.onChange |\n\n其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n`Field` 的 `rules` 和 `effects` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" effects={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {\n          visible: true,\n        });\n      } else {\n        formCore.setFieldProps('age', {\n          visible: false,\n        });\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" status=\"hide\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据。\n\n- `getFieldValue(name)`\n  获取某一 `Field` 的值\n- `getValues()`\n  获取表单的 values\n- `setFieldValue(name, value)`\n  设置某一 `Field` 的值\n- `setValues(values)`\n  设置某些 `Field` 的值\n- `getFieldError(name)`\n  获取某一 `Field` 的 error 信息\n- `getErrors()`\n  获取表单的 errors\n- `setFieldError(name, errMsg)`\n  设置某一 `Field` 的 error 信息\n- `setErrors(errors)`\n  设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`\n  获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`\n  设置某一 `Field` 的属性值\n- `submit()`\n  提交表单\n- `reset()`\n  重置表单\n\n也可以通过属性的方式获取到一些数据：\n- `formCore.values`\n  获取表单的所有值\n- `formCore.errors`\n  获取表单校验的错误信息\n- `formCore.pristine`\n  表单当前的 `values` 是否与 `initialValues` 相等\n\n## 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)\n","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.2-1_1561109154415_0.7872903166822858","host":"s3://npm-registry-packages"}},"0.1.2-2":{"name":"@ice/form","version":"0.1.2-2","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.2-2","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.2-2/build/index.html","dist":{"shasum":"af857d0ad7d7e62b1688818f4b0df8f9b787e5ed","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.2-2.tgz","fileCount":37,"integrity":"sha512-pcdua3dPj0O66LEY3OBFYY0fCEXzwROxWevCb6VWDzm985uBsfWeSPT+S60SoBM0O4chO0l0gUthZTjEYe35tA==","signatures":[{"sig":"MEYCIQDtDjD0Rs6Ug0FruBZ4EfLbk3fBuqZOZnnXWDdjVSXobwIhAOy0GIpAdDekdJvdWkqjtTmNkyI43zYksTOeh1kq6jfy","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2878273,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdDKNZCRA9TVsSAnZWagAAxlYP/Ah7QlqB5x1R4CcjFlD/\ngKp7W4/ResVzO7D0Mv38HdjXddCy0hnFUR/NgdAciWds+NPt0PX35fuM81mt\n1uSt7mpqqyZMopxpuxRmqYHhAzUFwMuxUZwuociN2+5ERCc7QoxonqB96ssu\n1WwVI8ueC5VZvL/weGeztZPAjx7X0A1ICPjpW/l7g1r6RaebZTQ8LyVL4v8S\nAMBUS3breQZkAuCuMQ1OA/MLJEV1GBjxywrGgsnuh6ccHn9jViAPx2lD1pd9\nlqxCjrFby4C4abrJ4fN07SSwyjDUEoylyI1ckJWl/5xebQSG0UVWBSYUUiLU\niCHFRTQPaqIcoHbJSP89W1dlfC20RfUqXDfuQLLqKERYp3TwZ9G6fosyelrh\nMlXoiLcIWVtzR2LUNkxk0E/S6YhDmIaFOE9N6AQE5QlPpCV2OCBoJrb2eOOe\nYKFH+dO5GUSX92eh5LW/KT4j0yk071KihtyDu8ZIY5jJZrjnN97w7+wDhOnO\nR11dl/YwK7XLDJdWNcyu0AjqWr1b6PXU2oEeqIcbseFiteSNnXRrLi/JaLvj\nVeVO3U5fGvlccCsnnx9DbnZcNpcqi67PEl6zCDLc0w0IjynTOiOZD627dX3I\npxFZ79V748qJJTz/dMxsJ6HfIdb+wCPjBDfHW1JmcALYwaY8IYCvndKrHhmh\nWgMA\r\n=Y6Ly\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"## 安装方法\n\n```bash\n$ npm install @ice/form --save\n```\n\n## 引用方法\n\n```js\nimport { Form, Field, FieldArray } from '@ice/form';\n```\n\n透出 Form、Field、FieldArray 三个组件。\n\n## 快速上手\n\n下面例子演示了如何创建一个简单的 form：\n\n```js\nimport React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Form, Field } from '@ice/form';\nimport { Button, Input } from '@alifd/next';\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nclass App extends Component {\n  async onSubmit(values) {\n    await sleep(300)\n    window.alert(JSON.stringify(values, 0, 2))\n  }\n\n  render() {\n    return (\n      <div>\n        <Form onSubmit={this.onSubmit}>\n          <div>Simple Form</div>\n          <Field label=\"年龄：\" name=\"age\" component={Input} />\n          <Field label=\"年龄：\" name=\"age\" component={Input} htmlType=\"number\" />\n          <Field label=\"简介：\" name=\"intro\" component={Input.TextArea} />\n          <Button htmlType=\"submit\">Submit</Button>\n        </Form>\n      </div>\n    );\n  }\n}\n\nReactDOM.render((\n  <App />\n), mountNode);\n```\n\n## Form 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| onChange |  表单变化回调   |  N    |   function   |    -    |   function(values: object, item: object) => void <br> 参数: <br> values: {object} 表单数据 <br> item: {object} 详细 <br> item.name: {string} 变化的组件名 <br> item.value: {string} 变化的数据 |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| effects |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n| renderField |  自定义 Field 布局   |  N    |   function   |   -   |   function({label, component, error}) => dom  <br> 参数: <br> label: {string/element} Field 的 label <br> component: {string/function} 待渲染的控件 <br> error: {string/element} Field 错误提示信息  |\n\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n`layout` 是个对象，包含 4 个属性：\n```js\n{\n  labelAlign: 'left',       // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right',  // label 文字对齐方式，'left'、'right'，默认 'right'\n  labelCol: 1,             // label 占的栅格宽度，共 6 等分，默认 1\n  wrapperCol: 3,           // 控件占的栅格宽度，共 6 等分，默认 3\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`effects` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  effects={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n监听该 `field` 的 `onChange` 事件，然后设置其他表单项的数据，从而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string/element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |  string/function   |    -    | 'input' 'textarea' Input Radio   |\n| value |  表单项的值    |  N    |  -  |    ''    |   -   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| effects |  联动规则   |  N    |   object   |    -    |   -   |\n| visible |  显示隐藏当前 Field   |  N    |   boolean   |  true  |   true/false  |\n| setValueFormatter |  格式化控件渲染值  |  N    |   function   |    |  function(savedValue) => renderValue  |\n| getValueFormatter |  格式化控件提交值  |  N    |   function   |    |  function(renderValue) => savedValue  |\n| layout |  设置当前 Field 的布局   |  N    |   object   |   同 Form layout   |  当前 Field 的 layout 会覆盖 Form 的 layout |\n| tips |  提示信息   |  N    |   string   |    |    |\n| valueName |  控件值的名称，比如，radio 的 valueName 为 'checked'，value 为 true/false  |  N    |   string   |    |  比如 Fusion 的 Switch 组件  |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方控件 onChange 的第一个参数不是 event 或者 value，可以主动设置对应的值。比如，接入控件的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)` |\n\n`style`、`className` 属性会传递到 Field 最外层 dom 上，其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n\n`Field` 的 `rules` 和 `effects` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" effects={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {\n          visible: true,\n        });\n      } else {\n        formCore.setFieldProps('age', {\n          visible: false,\n        });\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## FieldArray 组件\nFieldArray 表示渲染数组类型的数据，属性同 Field：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n>\n  <FieldArray label=\"新增顾客：\" name=\"customers\">\n    <Field name=\"customer0\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer1\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer2\" component={Input} placeholder=\"customer name\" />\n  </FieldArray>\n  <Field label=\"日期：\" name=\"date\" component={DatePicker} />\n  <Field label=\"\">\n    <Button htmlType=\"submit\">Submit</Button>\n  </Field>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据、状态等。\n\n- `getFieldValue(name)`\n  获取某一 `Field` 的值\n- `setFieldValue(name, value)`\n  设置某一 `Field` 的值\n- `getValues()`\n  获取表单的 values\n- `setValues(values, runEffects)`\n  设置表单的 values，runEffects 为 Boolean，表示设置 values 之后是否需要执行表单的 effects，默认 false\n- `getFieldError(name)`\n  获取某一 `Field` 的 error 信息\n- `setFieldError(name, errMsg)`\n  设置某一 `Field` 的 error 信息\n- `getErrors()`\n  获取所有 `Field` 的 error 信息\n- `setErrors(errors)`\n  设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`\n  获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`\n  设置某一 `Field` 的属性值\n- `submit()`\n  提交表单\n- `reset()`\n  重置表单\n\n也可以通过属性的方式获取到一些数据：\n- `formCore.values`\n  获取表单的所有值\n- `formCore.errors`\n  获取表单校验的错误信息\n- `formCore.pristine`\n  表单当前的 `values` 是否与 `initialValues` 相等\n\n## 延伸阅读\n### 开发 @ice/form 表单背景\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n### 组件特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n### 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n### 竞品对比\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n### 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)\n","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.2-2_1561109336763_0.8584711061792134","host":"s3://npm-registry-packages"}},"0.1.2":{"name":"@ice/form","version":"0.1.2","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.2","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.2/build/index.html","dist":{"shasum":"04acfc9535a538806b9eb4395359d456690e8270","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.2.tgz","fileCount":37,"integrity":"sha512-162fU62HnZILj4udo0vtRDTejwZnJqc4fMEGbwvM10gXOhhQDsqk4GHC5rnnriyLorljknfa5OnwuLqI4hkBZg==","signatures":[{"sig":"MEQCIC3hqLjHcGz/Z22uB5c9y4EO8gd0dbtXlzMREnSjDusFAiBEWJTCuVaUarWhxTvBYQIFmhMG7hS1f+s4Khydq7WLNw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2878163,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdEN7pCRA9TVsSAnZWagAAcgAQAIdx3QgCmYRYLc0qkHwj\nbfabOLHF6WAkpehzmIV+jLEefHG0ay0joeoPZvhOfdbayhybM+oYmAuiHYKD\nyaVrIxsFrttgqLXOC00QEM5iJseHl7SauET1uuigGmJ87gvPMcuwwiF2VhU7\n1WTmuAANOxFwoRMC7aNY6HKMGA1hUb0e2/x+y/XEMKTuR9VZSS9KTarGUGVx\n52eTgvnduWaPhi+77dX4gXO0lBOQL06TjhYKXo+V4Ro+M8o+L8SamC4tPjyX\n5k6zj64i121600kz0FjMkeWI+CN3Bwxe1m+KYjgqITo+5gZ7ElWOYI/MXh6W\n38BPXQp+QGguLf+YFQhMAYKqGAjfiFdxKDIdgUzlHwc+XYFhsWaDZDh1f9x9\nFPR3wrIc1zxGxw7V9Db5pkn6/nHc6Uwir8pp15PUOt2O2AR8asOkEeazJA67\nxE3UnXJoFtb2bCwFA/s3X8+fieEPbGD46qO+iytBWYXmbCIJ6VxCgl8o9AUe\n21uJgEovCoobdVvk66KO3rTA3PCqdSZsKLoHyJh1iljtIjOUxkwrZgl5Za0G\nNcxDNJPmZYAYjDQgxW7lUM+G67w/rlLm8YUFZJ9zyuV3IjclGQIE/QKMunIw\nKit9BF0wgLoiETlOc+/uBl6TQ6joZwNXdGrZxoyrEsybCGYbTrc6qtU3gBe+\nLc9G\r\n=kw8G\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.2_1561386728580_0.3417577125729623","host":"s3://npm-registry-packages"}},"0.1.3-0":{"name":"@ice/form","version":"0.1.3-0","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.3-0","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"},{"name":"yundong","email":"yundong.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.3-0/build/index.html","dist":{"shasum":"9797a94829a46de95bac6570d5fbab8a8a74fe72","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.3-0.tgz","fileCount":37,"integrity":"sha512-sa7ANz2mSBVyy1v9LYk3aGhEATH+5Kg2T7UoJlLL9bXFoMb2Dk2HjDTUIXZLoNfD9pqReXUvuNCfNb3kVHhG8Q==","signatures":[{"sig":"MEYCIQDPy5hJDfKbhi+DVUBywq/mVP5BArMZ61HJZuUi3fPBjQIhALxyA1FRg820/PRCGIIT9PsQFLYnik+YBfs55um/jdoi","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2884045,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdExagCRA9TVsSAnZWagAAZJwP/ApJcA9SL8YKPWM7UesT\ngyV5tIh/WFGDyamGFjpXBgdAIRvVMWZNKpDsqDwJjn3ll96rXJub363G8M+7\nqNxikyvMgsrmw3iB260yxxJmQB81ey/fAfDVK/aQLFTrZAHrtF08pICrXiQC\nkb0suAKHhoy2zsRmsAnLkeMqARwa4k2W0QNGHJF3BUnMeYbRKVXdoRY1JyR9\nm/07L5XKcYKE/Sx1YZK2I9ZQHwWSJoQE+mcZVh+CAfLRfstQfKxk3cuM0F1s\nDGpyR1KGC144RvhE/uE9Z3OR9NwIhHk7y3YCoSFt8y3VkxPNGz4gtXQtrnbL\nQWj9hOQwtuN+yspq4KuITgr99oMepq25tNZfvynGeFGduQv3GeSt99HAGax0\nJdsBNaiN2SHjYL+5zs/60A4ASsBj1F3mjVFaoIlfuHwK0yKuLtFv967cTD/X\nOiEXLIOBrktwD2cyje8BvnSuOBrO5jMMJIGbUW5/mniCs3mY5OIcR9qKzS4S\njQagXLs/c+Pvls30rcOycjcypZDBtkHVJOhbJ3h+9AKtC7RTz3cUTo6Vgel+\nwvVmrY7gh3WWqMoldMVUvVthr3HGw4bz/xtpiqDTYoBQqw1b5jKCTYAFlqID\n3V0zf+euNWKW7fl/N+tI04n5HPfcBEKdMP3BAs24OwLBv14AFXvIRjivJ0HX\nbTJw\r\n=fZCr\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"## 安装方法\n\n```bash\n$ npm install @ice/form --save\n```\n\n## 引用方法\n\n```js\nimport { Form, Field, FieldArray } from '@ice/form';\n```\n\n## 快速上手\n\n下面例子演示了如何创建一个简单的 form：\n\n```js\nimport React, { Component } from 'react';\nimport ReactDOM from 'react-dom';\nimport { Form, Field } from '@ice/form';\nimport { Button, Input } from '@alifd/next';\n\nconst sleep = ms => new Promise(resolve => setTimeout(resolve, ms))\n\nclass App extends Component {\n  async onSubmit(values) {\n    await sleep(300)\n    window.alert(JSON.stringify(values, 0, 2))\n  }\n\n  render() {\n    return (\n      <div>\n        <Form onSubmit={this.onSubmit}>\n          <div>Simple Form</div>\n          <Field label=\"姓名：\" name=\"username\" component={Input} placeholder=\"请输入名字\" />\n          <Field label=\"年龄：\" name=\"age\" component={Input} htmlType=\"number\" placeholder=\"请输入年龄\" />\n          <Field label=\"简介：\" name=\"intro\" component={Input.TextArea} />\n          <Button htmlType=\"submit\">Submit</Button>\n        </Form>\n      </div>\n    );\n  }\n}\n\nReactDOM.render((\n  <App />\n), mountNode);\n```\n\n## Form 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| onChange |  表单变化回调   |  N    |   function   |    -    |   function(values: object, item: object) => void <br> 参数: <br> values: {object} 表单数据 <br> item: {object} 详细 <br> item.name: {string} 变化的组件名 <br> item.value: {string} 变化的数据 |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| effects |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n| renderField |  自定义 Field 布局   |  N    |   function   |   -   |   function({label, component, error}) => dom  <br> 参数: <br> label: {string/element} Field 的 label <br> component: {string/function} 待渲染的控件 <br> error: {string/element} Field 错误提示信息  |\n\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n`layout` 是个对象，包含 4 个属性：\n```js\n{\n  labelAlign: 'left',       // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right',  // label 文字对齐方式，'left'、'right'，默认 'right'\n  labelCol: 1,             // label 占的栅格宽度，共 6 等分，默认 1\n  wrapperCol: 3,           // 控件占的栅格宽度，共 6 等分，默认 3\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`effects` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  effects={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n监听该 `field` 的 `onChange` 事件，然后设置其他表单项的数据，从而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string/element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |  string/function   |    -    | 'input' 'textarea' Input Radio   |\n| value |  表单项的值    |  N    |  -  |    ''    |   -   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| effects |  联动规则   |  N    |   object   |    -    |   -   |\n| visible |  显示隐藏当前 Field   |  N    |   boolean   |  true  |   true/false  |\n| setValueFormatter |  格式化控件渲染值  |  N    |   function   |    |  function(savedValue) => renderValue  |\n| getValueFormatter |  格式化控件提交值  |  N    |   function   |    |  function(renderValue) => savedValue  |\n| layout |  设置当前 Field 的布局   |  N    |   object   |   同 Form layout   |  当前 Field 的 layout 会覆盖 Form 的 layout |\n| tips |  提示信息   |  N    |   string   |    |    |\n| valueName |  控件值的名称，比如，radio 的 valueName 为 'checked'，value 为 true/false  |  N    |   string   |    |  比如 Fusion 的 Switch 组件  |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方控件 onChange 的第一个参数不是 event 或者 value，可以主动设置对应的值。比如，接入控件的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)` |\n\n`style`、`className` 属性会传递到 Field 最外层 dom 上，其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n\n`Field` 的 `rules` 和 `effects` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" effects={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {\n          visible: true,\n        });\n      } else {\n        formCore.setFieldProps('age', {\n          visible: false,\n        });\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## FieldArray 组件\nFieldArray 表示渲染数组类型的数据，属性同 Field：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n>\n  <FieldArray label=\"新增顾客：\" name=\"customers\">\n    <Field name=\"customer0\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer1\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer2\" component={Input} placeholder=\"customer name\" />\n  </FieldArray>\n  <Field label=\"日期：\" name=\"date\" component={DatePicker} />\n  <Field label=\"\">\n    <Button htmlType=\"submit\">Submit</Button>\n  </Field>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据、状态等。\n\n- `getFieldValue(name)`\n  获取某一 `Field` 的值\n- `setFieldValue(name, value)`\n  设置某一 `Field` 的值\n- `getValues()`\n  获取表单的 values\n- `setValues(values, runEffects)`\n  设置表单的 values，runEffects 为 Boolean，表示设置 values 之后是否需要执行表单的 effects，默认 false\n- `getFieldError(name)`\n  获取某一 `Field` 的 error 信息\n- `setFieldError(name, errMsg)`\n  设置某一 `Field` 的 error 信息\n- `getErrors()`\n  获取所有 `Field` 的 error 信息\n- `setErrors(errors)`\n  设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`\n  获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`\n  设置某一 `Field` 的属性值\n- `submit()`\n  提交表单\n- `reset(initialValues)`\n  重置表单值为表单初始化时的默认值，如果表单初始化时没有默认值，则清空表单；\n  如果传了参数 initialValues，则 initialValues 会成为新的表单默认值\n\n也可以通过属性的方式获取到一些数据：\n- `formCore.values`\n  获取表单的所有值\n- `formCore.errors`\n  获取表单校验的错误信息\n- `formCore.pristine`\n  表单当前的 `values` 是否与 `initialValues` 相等\n\n## 延伸阅读\n### 开发 @ice/form 表单背景\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n### 组件特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n### 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n### 竞品对比\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n### 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)\n","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.3-0_1561532064170_0.6988859377660497","host":"s3://npm-registry-packages"}},"0.1.3":{"name":"@ice/form","version":"0.1.3","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.3","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"},{"name":"yundong","email":"yundong.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.3/build/index.html","dist":{"shasum":"d959de6e20b4afd08fe45a5fd1b679aeb247191d","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.3.tgz","fileCount":37,"integrity":"sha512-pwd3p0hyH0jL+PYTI0liq0Mj9PhTh9EqdJYeWB2MkoPwS3hra5kaNoff0nQ1SZk0vSq/gRpmmpxgYfc/4zBS5A==","signatures":[{"sig":"MEUCIQD2YoOwAhHMTMt0s/rT+TWcVTonPX8Q9JqloS8Ye7B9oAIgU7+dahoRVAjEIiY/7U/BPf22HcJygBar6EfDOZ3arIk=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2884041,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdEx5FCRA9TVsSAnZWagAA4OMP/RJ51y1bskmzBU8LK4XN\nzaGM3SYhuSCHmO8/yeeGNXBmn//FSTdP+Wlv0h+xNdQeshcb/nfapveJham8\nNiwRpIWQ6D66VdC+3/j5mp9xTb7+C5owv3CJYLJmyweKKiWLSxkG7LYuS3bH\nkjfEBhXO/24rMucbWKlUviIUe8wm5AwVGWyjfJ2LOFHId0U6gLcN4hJsYdC/\njZ8e68Rp8FLDkRJ96w38OorWgsGqW8Vl4Hbb3eWazXSV7iuXa1OjONUTWXpS\nBK1qLpIMG5iwSTVjTN/oaYQKPBweSPbnN2uDEmS6hkRp6plKSwZBSuXV9bp3\nMYFgEOTPP4Z9q8dmlJY0q/Aw6ZK8wKhABuQyvMhEwkGK6EM6N1GrFRr7KkHP\nf4M7wa7wFkvWDpEjEld7kIV2GFfE20F9QhTSffNvX4C3YxKDYM6B5o7TScI/\nvl9JOk9T3nijXqxT1Hk/wyvQa8EYDEH3ltlbhYJLHWcCE84+dGfm5mvrE1vj\ndm6jnHAZvAg4hqkhHXYvvF2iw+RDK+g4Q7j9JLgudVrkvoVoo/VL7GRlONKc\nVkprVbvSPhT8E/v9XqgGFsrp8gxR2LJt6b17N5P2mHB6g9VIUgXy+aFUkgKm\nfnsMXkOpI29N3PYtatTSaD9awd4HiJumVEssCzJ/d0pUGZi4hwV/TPZINxk+\nN5eP\r\n=ydIz\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"componentConfig":{"name":"@ice/form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.3_1561534020981_0.7387685806520476","host":"s3://npm-registry-packages"}},"0.1.4-0":{"name":"@ice/form","version":"0.1.4-0","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.4-0","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"},{"name":"yundong","email":"yundong.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.4-0/build/index.html","dist":{"shasum":"7f61301067a3050aa784fcc54e59f5de15979812","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.4-0.tgz","fileCount":37,"integrity":"sha512-Dc5UEoLwo2wE8RVrp9VWF8nEJbU/qMP2z6svkUCNQqZ+mRJ7gJykzowKSktjQ2QXzopezBH4rmOIGWFp6vKKEw==","signatures":[{"sig":"MEUCIC5Xchvzv9DxZdQ7CNDSFc+6xHJJGIYVHEXpoVDz9knsAiEAgvdW2Sv83x8tQRge3ckfB0fHWBePplzKb3SfevHcjdo=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2875092,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdFJkVCRA9TVsSAnZWagAAmJUP/isPDJg6xhI0HsLhfLoJ\nCqRYbjMWt/zlakDBb5nQSRFDhB+/CtVYC4aWp3h4fb0n2ASIR+Jf/50vZX63\nVPz2Q8fqm5dE8Vu9J6LIi7dJ1Fei0la0Zw+sYVh+rGiEDyx2VuMQNd+5OEvC\nBgyzuCZqLWd/5UUPgPfYB39i4GblPMzufx+5KrDgX2uTRwZ9Xp7ssMkxZbN+\nxhTszTmqWvd9BqbH/RiVvP1JxVJFFBIFaDPABryt/OyvpQExN8gll+xfWqCr\nThC+eVjOafDil+YMzcxi0tvPEZU+/mUYW4Gnv8PjrkzkUo8bu4lrDDqETnrG\n5kz/1JyhY/AwLLKO9d/YMr2oocKkCWZBf7fYNP7e6BY2TP0l1RfKEqNeSSNy\nA3pe388OqUM+aBMgBM1Ixl9EN22kMgODhZ8i0rY/n+wq+qFE03HzHutoOBOa\n1CwvYx3HwmSKrvsgGxkItl7q/edM3OyN6oehuLI1GOmqzT30XXPr7IL8n2rh\nr4o+w2b2IiR96DcyCRycisemgVv3/E6AzVGDtXFKGdI/nCj4uOdNcxFn/NaJ\nJ8yBv1P3Z0x+IW6N448dVExsT8QgKuPu0x3Sx5TnGpzxxRzUMGZuVzynLm6y\nMEFOosCmaJYOrAYDjmTLzTqNvqerJ8nTv7hP9yfsgicj02hrctNlXjef1/M7\n4CZk\r\n=mauS\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"---\ntitle: IceForm\ncategory: Components\nchinese: 表单组件\n---\n\n表单组件\n\n## 参数（Props）\n\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| onChange |  表单变化回调   |  N    |   function   |    -    |   function(values: object, item: object) => void <br> 参数: <br> values: {object} 表单数据 <br> item: {object} 详细 <br> item.name: {string} 变化的组件名 <br> item.value: {string} 变化的数据 |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| effects |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n| renderField |  自定义 Field 布局   |  N    |   function   |   -   |   function({label, component, error}) => dom  <br> 参数: <br> label: {string/element} Field 的 label <br> component: {string/function} 待渲染的控件 <br> error: {string/element} Field 错误提示信息  |\n\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n`layout` 是个对象，包含 4 个属性：\n\n```js\n{\n  labelAlign: 'left',       // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right',  // label 文字对齐方式，'left'、'right'，默认 'right'\n  labelCol: 1,             // label 占的栅格宽度，共 12 等分，默认 2\n  wrapperCol: 3,           // 控件占的栅格宽度，共 12 等分，默认 6\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`effects` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  effects={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n监听该 `field` 的 `onChange` 事件，然后设置其他表单项的数据，从而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string/element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |  string/function   |    -    | 'input' 'textarea' Input Radio   |\n| value |  表单项的值    |  N    |  -  |    ''    |   -   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| effects |  联动规则   |  N    |   object   |    -    |   -   |\n| visible |  显示隐藏当前 Field   |  N    |   boolean   |  true  |   true/false  |\n| setValueFormatter |  格式化控件渲染值  |  N    |   function   |    |  function(savedValue) => renderValue  |\n| getValueFormatter |  格式化控件提交值  |  N    |   function   |    |  function(renderValue) => savedValue  |\n| layout |  设置当前 Field 的布局   |  N    |   object   |   同 Form layout   |  当前 Field 的 layout 会覆盖 Form 的 layout |\n| tips |  提示信息   |  N    |   string   |    |    |\n| valueName |  控件值的名称，比如，radio 的 valueName 为 'checked'，value 为 true/false  |  N    |   string   |    |  比如 Fusion 的 Switch 组件  |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方控件 onChange 的第一个参数不是 event 或者 value，可以主动设置对应的值。比如，接入控件的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)` |\n\n`style`、`className` 属性会传递到 Field 最外层 dom 上，其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n\n`Field` 的 `rules` 和 `effects` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" effects={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {\n          visible: true,\n        });\n      } else {\n        formCore.setFieldProps('age', {\n          visible: false,\n        });\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## FieldArray 组件\n\nFieldArray 表示渲染数组类型的数据，属性同 Field：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n>\n  <FieldArray label=\"新增顾客：\" name=\"customers\">\n    <Field name=\"customer0\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer1\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer2\" component={Input} placeholder=\"customer name\" />\n  </FieldArray>\n  <Field label=\"日期：\" name=\"date\" component={DatePicker} />\n  <Field label=\"\">\n    <Button htmlType=\"submit\">Submit</Button>\n  </Field>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据、状态等。\n\n- `getFieldValue(name)`：获取某一 `Field` 的值\n- `setFieldValue(name, value)`：设置某一 `Field` 的值\n- `getValues()`：获取表单的 values\n- `setValues(values, runEffects)`：设置表单的 values，runEffects 为 Boolean，表示设置 values 之后是否需要执行表单的 effects，默认 false\n- `getFieldError(name)`：获取某一 `Field` 的 error 信息\n- `setFieldError(name, errMsg)`：设置某一 `Field` 的 error 信息\n- `getErrors()`：获取所有 `Field` 的 error 信息\n- `setErrors(errors)`：设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`：获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`：设置某一 `Field` 的属性值\n- `submit()`：提交表单\n- `reset(initialValues)`：重置表单值为表单初始化时的默认值，如果表单初始化时没有默认值，则清空表单；如果传了参数 initialValues，则 initialValues 会成为新的表单默认值\n\n也可以通过属性的方式获取到一些数据：\n\n- `formCore.values`：获取表单的所有值\n- `formCore.errors`：获取表单校验的错误信息\n- `formCore.pristine`：表单当前的 `values` 是否与 `initialValues` 相等\n\n## 延伸阅读\n\n### 开发 @ice/form 表单背景\n\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n### 组件特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n### 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n### 竞品对比\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n### 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"ice-form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.4-0_1561630996806_0.5564259155565094","host":"s3://npm-registry-packages"}},"0.1.4":{"name":"@ice/form","version":"0.1.4","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.4","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"},{"name":"yundong","email":"yundong.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.4/build/index.html","dist":{"shasum":"45aaf8a568c4502f665ce6d1d93e90b7469675fd","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.4.tgz","fileCount":37,"integrity":"sha512-aRHrCLXcHlWAoNdiTowpb2aPPd3dwMrIb6tL0GoJOHb1c7v12+S5L5aOfp+FsUMUh3X1gvWBmBo1fvhIGq/lXQ==","signatures":[{"sig":"MEYCIQCNBo1TWxVV+a+ARYwT1r0+c1kOCeEJMY4lK5XPlKhsrwIhAOtMmqlgQbMbmkWer3m3L6+xGWCxTkeodZ2KNjjMRdXG","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2875088,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdFJpWCRA9TVsSAnZWagAA/qMP/R/95LhfROH6TbKiiNEE\nO4pkV1hXnGUU7Xx+UF9o0kJz9zmSV8cl60X/2W1zYrWvKJ3zJwrvKsif/D5L\n0r+LlWxPZ9lyFPDJFpNDRR0cz36lvibHlUpw6NDZJrgVBJZIFzKQZafoZfoM\nI9wj3vd3cTpYOlHUdLoz3jATnVRV8yLdoJmqWKrkKOXvbN+2+CPzajm4tiTJ\np2w/e8yQs7VX762JX27Ax7ZEjQCBVyYFgLwN28ZfB1XAkzr+DwXRbDYqc6I7\nce7EJti84jKoMXSWL7OoTAaYRcz+EQ2l+YaDrAgzvAH0EoX5S1gkiKbmpBG1\nVD1bGTarbpTIEz5BM2qULn1SsG1VMTHHTG+r4EF2fnmeeQbet9jnQ0X5u0oz\nwaOWKPnk4/JlFuVAW2xHegfoxo1uHouD7DdIiQbezFvskXndI/DG+Ab+FI9u\nzyEGn/X/Y+HcqT8+QJKu9mplF17mI8QxGw0exBvXxGGubnm2zaYyagqmbeiO\n2awYhaHjPqgAtCEKa8ZZowRQGsr1wCoP5THKcVaZgF1ZnL4t1OXXTLdwqKOA\nOgTg47negGD2XfbRDWjQtQMg2rspWqKgJPxlL5MCtwz6uXOZqZelpaqHF0wT\n6NZTxiqXsMUfg5IKaYHvRC6Wza68vN7edfsSkYrUO9Zs43WZmcGsRdJha5rn\naynH\r\n=CmdU\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"componentConfig":{"name":"ice-form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.4_1561631317469_0.755184331879065","host":"s3://npm-registry-packages"}},"0.1.5-0":{"name":"@ice/form","version":"0.1.5-0","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.5-0","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"},{"name":"yundong","email":"yundong.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.5-0/build/index.html","dist":{"shasum":"855475bc704a5d0620d21c05c88e38c39a54e949","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.5-0.tgz","fileCount":37,"integrity":"sha512-ky002F4sdbeK0XVeNSVsHYLVS5xgslVd86SJ8FIZP0T/zgXJxACmHR4qRnNWLzXYKfs/+9FmeDHCaUrRPVK4+w==","signatures":[{"sig":"MEUCIQCZskf8jYRT3rqOgcw8JgzbVpvMSkYBukqX0l054HTF2QIgLJQEKzz5V7skAAnahqsYSQyWy9jw84lEC6lYZqAg+ak=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2875710,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdGwG9CRA9TVsSAnZWagAAezkQAIxuQbxuON733rEnNObi\nzju1c0YaQwVHP+LMhwC1MjeScT1PFDoJb7/R0qHfZC8hHuHDIbmtJve6zTgB\nxVRrZn6C523z22wfY+7xsCx4BzbxzouRDQlixPitDFLf56S3x8ofplkymLDG\nUATNLx/WjL5zxtx942lAnxzDBHpUm1NF2xJLzYWxVBrnGDutTOe8e6s/75uW\nj9GOkH6nZ0eYvYxqn0gRn+clUCRrDE8hNrr+eV3b49AQSqoWhSHwp2uxeu84\n5j0NUppQ+tNwyiB2/ITfbfqCLKtRxdiiWeQcG+fMA35gMOvwczQbJ9Erp8Ck\n3LBqMT1vFb05cQsAW3d0citwXhfLO+rNn3ZK7LEqPkrDXgHC3tNxr5KbQCsX\nBgRiisAtEdndSbzrbOCMld3qBCXL75IEnLGlLSksEQ8Xl2fg4pz57L38gkMR\nyp2rpTZMFBeoMirN5M3anHWSxgYxP1MezMn4StPT+jUVEXn65g5l6/DeF2BC\n4WDN9fTU8OG3rgOmg7KFcN2Qpzp8/d6XqIUUraYC8TZKITXnm6XzLMqo9JQv\nhC+DVqJSabIPgARwhFtuQxQKcLFMsIaKC4xR2kK6TJJMsj5HLRhlPQ4VpPnr\nxvt+AbMcLoRervd+ORPtU0EBLqug4TyU7RxNfNOkJXpa2zqi9PA8dXnBeem+\n0Wdv\r\n=TnEr\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","readme":"---\ntitle: IceForm\ncategory: Components\nchinese: 表单组件\n---\n\n表单组件\n\n## 参数（Props）\n\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| onChange |  表单变化回调   |  N    |   function   |    -    |   function(values: object, item: object) => void <br> 参数: <br> values: {object} 表单数据 <br> item: {object} 详细 <br> item.name: {string} 变化的组件名 <br> item.value: {string} 变化的数据 |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| effects |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n| renderField |  自定义 Field 布局   |  N    |   function   |   -   |   function({label, component, error}) => dom  <br> 参数: <br> label: {string/element} Field 的 label <br> component: {string/function} 待渲染的控件 <br> error: {string/element} Field 错误提示信息  |\n\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n`layout` 是个对象，包含 4 个属性：\n\n```js\n{\n  labelAlign: 'left',       // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right',  // label 文字对齐方式，'left'、'right'，默认 'right'\n  labelCol: 1,             // label 占的栅格宽度，共 12 等分，默认 2\n  wrapperCol: 3,           // 控件占的栅格宽度，共 12 等分，默认 6\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`effects` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  effects={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n监听该 `field` 的 `onChange` 事件，然后设置其他表单项的数据，从而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string/element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |  string/function   |    -    | 'input' 'textarea' Input Radio   |\n| value |  表单项的值    |  N    |  -  |    ''    |   -   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| effects |  联动规则   |  N    |   object   |    -    |   -   |\n| visible |  显示隐藏当前 Field   |  N    |   boolean   |  true  |   true/false  |\n| setValueFormatter |  格式化控件渲染值  |  N    |   function   |    |  function(savedValue) => renderValue  |\n| getValueFormatter |  格式化控件提交值  |  N    |   function   |    |  function(renderValue) => savedValue  |\n| layout |  设置当前 Field 的布局   |  N    |   object   |   同 Form layout   |  当前 Field 的 layout 会覆盖 Form 的 layout |\n| tips |  提示信息   |  N    |   string   |    |    |\n| valueName |  控件值的名称，比如，radio 的 valueName 为 'checked'，value 为 true/false  |  N    |   string   |    |  比如 Fusion 的 Switch 组件  |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方控件 onChange 的第一个参数不是 event 或者 value，可以主动设置对应的值。比如，接入控件的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)` |\n\n`style`、`className` 属性会传递到 Field 最外层 dom 上，其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n\n`Field` 的 `rules` 和 `effects` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" effects={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {\n          visible: true,\n        });\n      } else {\n        formCore.setFieldProps('age', {\n          visible: false,\n        });\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## FieldArray 组件\n\nFieldArray 表示渲染数组类型的数据，属性同 Field：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n>\n  <FieldArray label=\"新增顾客：\" name=\"customers\">\n    <Field name=\"customer0\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer1\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer2\" component={Input} placeholder=\"customer name\" />\n  </FieldArray>\n  <Field label=\"日期：\" name=\"date\" component={DatePicker} />\n  <Field label=\"\">\n    <Button htmlType=\"submit\">Submit</Button>\n  </Field>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据、状态等。\n\n- `getFieldValue(name)`：获取某一 `Field` 的值\n- `setFieldValue(name, value)`：设置某一 `Field` 的值\n- `getValues()`：获取表单的 values\n- `setValues(values, runEffects)`：设置表单的 values，runEffects 为 Boolean，表示设置 values 之后是否需要执行表单的 effects，默认 false\n- `getFieldError(name)`：获取某一 `Field` 的 error 信息\n- `setFieldError(name, errMsg)`：设置某一 `Field` 的 error 信息\n- `getErrors()`：获取所有 `Field` 的 error 信息\n- `setErrors(errors)`：设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`：获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`：设置某一 `Field` 的属性值\n- `submit()`：提交表单\n- `reset(initialValues)`：重置表单值为表单初始化时的默认值，如果表单初始化时没有默认值，则清空表单；如果传了参数 initialValues，则 initialValues 会成为新的表单默认值\n\n也可以通过属性的方式获取到一些数据：\n\n- `formCore.values`：获取表单的所有值\n- `formCore.errors`：获取表单校验的错误信息\n- `formCore.pristine`：表单当前的 `values` 是否与 `initialValues` 相等\n\n## 延伸阅读\n\n### 开发 @ice/form 表单背景\n\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n### 组件特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n### 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n### 竞品对比\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n### 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"readmeFilename":"README.md","componentConfig":{"name":"ice-form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.5-0_1562051004248_0.9780104215829035","host":"s3://npm-registry-packages"}},"0.1.5":{"name":"@ice/form","version":"0.1.5","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.5","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"sobear","email":"sobear.me@gmail.com"},{"name":"yundong","email":"yundong.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.5/build/index.html","dist":{"shasum":"e1aff177ec0f6b645aecaab5ac35bf57f7ff0281","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.5.tgz","fileCount":37,"integrity":"sha512-a5+ONsEPK6AWyymE7lW6PnT6XTnb7S7s3pbwCVzPvEGZFDzd3ihj65c2FWz6Gz29nmdn1gd8mo5/UBm9RnJFTw==","signatures":[{"sig":"MEQCICgQQNAx9OUwxujuLupPJnwGcJXDqy9UrdvMu8m+VxxtAiByT0NrSaBQd0kjuG5GadMTItWorU/2f4dyvvAKPLbPmg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":2875706,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdGwIQCRA9TVsSAnZWagAA+iYP/3BlMdv/StbrbTKYEnSA\nyoDxqcir3TfAYofx2swJPasVQi/9ZUin6Qx5VBsX/e1bUjSLBiSTUN88zQZL\nyW/dXsjBqR8yppdBvAJMDqQQIxpM4ET52AIZive1ZV9Nkp5e5mj//0BRbN/G\nJCAbWY+JmlXYSV92CMPoNHQyfFrXfHWz25hzIl436UX5xSZPDfM2HSJYrT97\nOhW2p65nnQM2bbTg6UBR6Gi4tgR1kgZ+jl+FXhG+L9aQI0lX3axpSsKnIdzt\nh5HP69AcoSHb2ZK6Jxkx6dbXZJTxohfAYhPViRN5/r2uwuYgpkstWqT7VbPw\nAHDf4KZJs63FqiPtD0jXtBQxBqs4iWoYwSsCFuITDkRX0sRiafc4Uv3wPDvp\nzlfIrTXjxlDhmc2MowdK6brnOc2717qbieNEv9PSgmG5JeKTfaS6jAPrfsJ6\nmVIpuS0joyfUY1SNgYB2zNQxt4n/1/P5gVZ6TR/5qBnkhc0sZJdCL/aLmxO8\nC21lWcMeeireB2zjOpCa4E+chJQjno72VQ/PWlYkxCfIx0euwzwYNEj/J3X3\nOt4TYGKslh26M35dZj1ETJcYOcgoLdi6yzg5pCyMHtqDD8wkfYcSpPn+lBPJ\npoUtLqe+v0MfZHAYETTl7jjUZYaK2Gwx0/H+C6T4DAjmZRckjzcQkfMIAoEk\nNaw1\r\n=kGQ0\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","scripts":{"lint":"eslint . --ext '.js,.jsx' --fix","build":"ice-scripts build","start":"ice-scripts dev","prepublishOnly":"npm run build"},"_npmUser":{"name":"boiawang","email":"zhengwang2314@gmail.com"},"_npmVersion":"5.6.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"8.9.4","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"componentConfig":{"name":"ice-form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","eslint":"^5.16.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","ice-scripts":"^2.0.1","babel-eslint":"^10.0.1","ice-plugin-antd":"^0.1.3","ice-plugin-fusion":"^0.1.5","eslint-plugin-babel":"^5.3.0","eslint-plugin-react":"^7.13.0","eslint-config-airbnb":"^17.1.0","eslint-plugin-import":"^2.17.3","ice-plugin-component":"^0.1.2","@icedesign/form-binder":"^1.0.6","eslint-plugin-jsx-a11y":"^6.2.1"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.5_1562051087409_0.7772684207460019","host":"s3://npm-registry-packages"}},"0.1.6":{"name":"@ice/form","version":"0.1.6","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.6","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"jasonintju","email":"jasonintju@gmail.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"oraaange","email":"oraaangecolin@gmail.com"},{"name":"sobear","email":"sobear.me@gmail.com"},{"name":"temper357","email":"temper357@gmail.com"},{"name":"yundong","email":"yundong.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.6/build/index.html","dist":{"shasum":"fdecc189acc660f16713837ac25b6cf79fe6e042","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.6.tgz","fileCount":39,"integrity":"sha512-ZC1L2LJPBgjUsFVMX4SVR2u69E52r9HzbSAGu13+WIj2YfxVR/C5669QFxzQcTn8eQysskvrYADVPvxCryTz2A==","signatures":[{"sig":"MEQCIGmj+UzDcva1hWYPVjo3TDGxzptD3/iC3LXJHRUFyvPcAiAzYwFKqaYCmFdjzBOHz39Z+CxgceBjBuDDWjLDI1QZUA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":3744327,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdOXYBCRA9TVsSAnZWagAAF0sQAJBonHI3p6Yw2U1ajopr\nB8CIoCclLJk+rEpGgC8/CXt/N6pnisbmjwJJRh5rPjXez9/+7n2IITTPph/j\n13/Z8KmChWMwnXgSRw9UBguqfL0NKoLslP5QxOqKJJEQQ6+4VjtFTX1kz0wX\nD9ktayPQa53anCqc7qvn84cmRLHvdOK1Q0py9zqMpeG9nd12l9MfBD72XXq3\nSCvccEC874itfelba87j8bF/ATJKkaq5tXMfYJzg2g4AFde5nqG5NjbFDszW\nCnLDbhtYDAEkQCqwJSHx5ldCVDZPZ+ZVz/PANgBvm25prsw6CLffnBdzDm01\nSLI13GU95Wb93AixfgNjIfDJQElN+aSe13C2nDsUuBs+bYe30IJE+HHFkbF9\nEs6LhBNb1iI6JVwggo9c1XowZPfINm2bzN+rOZz9/fM2jjydgLUl43JynrUL\nKyxnp7KHSPtz/ixBOlYt1nRVJglkAn9X3kdc0ADQMiDBuKRg2JYGSPpNVIzC\n/XZ7FHW3gveqqJSsno7Ev1P0EaUJ+eg9e8W1Qih95sJTz7tnMmfU+KN/uoRn\n/dylLefJbKvcI3cOVl1mIZHNnc4JeodoHJ4EDXknn9rYZxbKmMw+35joeRDO\n3yFPB13AsNH9PVybU80vmNBk3iiaXv+u3BlK4AhpjfJFzPsISUBIgFR7JVoD\nzqgw\r\n=LgE/\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","scripts":{"build":"../../node_modules/.bin/ice-scripts build --config ../../ice.component.config.js","start":"../../node_modules/.bin/ice-scripts dev --config ../../ice.component.config.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"jasonintju","email":"jasonintju@gmail.com"},"_npmVersion":"6.8.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"10.12.0","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"componentConfig":{"name":"ice-form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","@icedesign/form-binder":"^1.0.6"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.6_1564046848498_0.5469816430221011","host":"s3://npm-registry-packages"}},"0.1.7":{"name":"@ice/form","version":"0.1.7","keywords":["ice","react","component"],"license":"MIT","_id":"@ice/form@0.1.7","maintainers":[{"name":"alvinhui","email":"alvinxwt@gmail.com"},{"name":"boiawang","email":"zhengwang2314@gmail.com"},{"name":"clarkxia","email":"xiawenwu41@163.com"},{"name":"jasonintju","email":"jasonintju@gmail.com"},{"name":"lip966","email":"470040845@qq.com"},{"name":"oraaange","email":"oraaangecolin@gmail.com"},{"name":"sobear","email":"sobear.me@gmail.com"},{"name":"temper357","email":"temper357@gmail.com"},{"name":"yundong","email":"yundong.me@gmail.com"}],"homepage":"https://unpkg.com/@ice/form@0.1.7/build/index.html","dist":{"shasum":"11363ff0dcf1388ed7deb2a0cc12c861d61ec485","tarball":"https://registry.npmjs.org/@ice/form/-/form-0.1.7.tgz","fileCount":39,"integrity":"sha512-oos0TbE4GAUj+GG2cUn1gXVI2AHym894He3B8SjaStZ3E3rzqUHEWhXjd7BwD0OMCnHv0fS+V6l+igzEdAZnrg==","signatures":[{"sig":"MEQCIHIfMDqK7EsRjWEz8IC1FSWVUxy4lnWKnTNLvrN7eOv3AiB1U52V3OgieeI2iIl5oTyyjM9ivHmEzXo9GSMm+1klLg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":3744472,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdOYktCRA9TVsSAnZWagAAWwwQAIRG/FlztywUpXVi/zHn\nEGqADdx7ZD5WC4O2rNxruiiXWOiX5PNcKBNk2hVip6fJX5eyJNHFdDBgF2B2\n3W0OFjygcfiUq2WNXySqnC1iVQ4As5ICoEzOFiVUwe0hmPZeMGUx6PKEhasc\nnzPg7aMmzvI0OOPTJFvztiipdMYt1EDTVtZtA436G8oN39C+R5NG0MPc424D\nLP9CPeXptQtAvSPjUOARhYANFCFzetv1cLbrf2XbPmkm2TGfxoVkKrN22408\nGkyVAOVBOu1Blmdl8dDpUqvT0Hcdzg+VNGyw6jPxO/utW8uPI0pt1OZmLKEl\n47E/yg6Hpr8Gz62b8zeXrukcpWDvJa8zN3sFyATux+TtTuv55G9LpbwVDcXC\nTZZu7eqsIsd8pbV4yTpHy8cxuK0xZ671yxDtQeR+dl0v+dClPt4BfYaUPZTx\nzAqnnqLe1toDtPibKENiTzPgEJjoaDQuJ41CjDl49Lfo0HODO6qX/xP59acs\nM/TFHKaeQbYecwVHNkRRZl7BaoizDBKOEJNbzpVPeKIOY3OwKELkoeJPvNJk\n3JIatzIXhcy7R5eUmpVZGaTSMwCjUi9I1qq6s1HVh33C4M5/Cso0PyMr+LUN\n/iytiBMsITdIiDdseuRTv+V+NzZsNFoSbjd8AJiS5UJIS8GMQjVCGo5Wz3Bt\n9pbR\r\n=Nvnt\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/index.js","scripts":{"build":"../../node_modules/.bin/ice-scripts build --config ../../ice.component.config.js","start":"../../node_modules/.bin/ice-scripts dev --config ../../ice.component.config.js","prepublishOnly":"npm run build"},"_npmUser":{"name":"jasonintju","email":"jasonintju@gmail.com"},"_npmVersion":"6.8.0","description":"ICE 表单组件","directories":{},"_nodeVersion":"10.12.0","dependencies":{"classnames":"^2.2.6","prop-types":"^15.5.8","lodash.isequal":"^4.5.0","async-validator":"^1.11.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"componentConfig":{"name":"ice-form","title":"ICE 表单组件","categories":["其他"]},"devDependencies":{"antd":"^3.18.2","react":"^16.3.0","react-dom":"^16.3.0","@alifd/next":"^1.15.3","@icedesign/form-binder":"^1.0.6"},"peerDependencies":{"react":"^16.3.0"},"_npmOperationalInternal":{"tmp":"tmp/form_0.1.7_1564051757156_0.8988309335034081","host":"s3://npm-registry-packages"}}},"time":{"created":"2019-05-29T11:18:52.270Z","modified":"2026-01-06T10:10:19.123Z","0.1.0-0":"2019-05-29T11:18:52.642Z","0.1.0-1":"2019-05-30T03:59:25.042Z","0.1.0-2":"2019-05-30T04:08:05.059Z","0.1.0-3":"2019-06-03T09:41:50.862Z","0.1.0-4":"2019-06-03T09:53:18.898Z","0.1.0-5":"2019-06-06T05:52:31.119Z","0.1.0-6":"2019-06-06T06:49:59.969Z","0.1.0-7":"2019-06-06T07:30:26.425Z","0.1.0-8":"2019-06-06T07:47:34.114Z","0.1.0":"2019-06-11T03:30:28.458Z","0.1.1":"2019-06-14T09:09:09.161Z","0.1.2-0":"2019-06-21T03:09:53.898Z","0.1.2-1":"2019-06-21T09:25:54.665Z","0.1.2-2":"2019-06-21T09:28:57.011Z","0.1.2":"2019-06-24T14:32:08.885Z","0.1.3-0":"2019-06-26T06:54:24.339Z","0.1.3":"2019-06-26T07:27:01.252Z","0.1.4-0":"2019-06-27T10:23:17.032Z","0.1.4":"2019-06-27T10:28:37.685Z","0.1.5-0":"2019-07-02T07:03:24.837Z","0.1.5":"2019-07-02T07:04:47.573Z","0.1.6":"2019-07-25T09:27:28.737Z","0.1.7":"2019-07-25T10:49:17.371Z"},"license":"MIT","homepage":"https://unpkg.com/@ice/form@0.1.7/build/index.html","keywords":["ice","react","component"],"description":"ICE 表单组件","maintainers":[{"email":"answershuto@gmail.com","name":"answershuto"},{"email":"chenjun1011@gmail.com","name":"chenjun1011"},{"email":"xiawenwu41@gmail.com","name":"clarkxia"},{"email":"rax-public@alibaba-inc.com","name":"rax-publisher"},{"email":"mrgitservice@outlook.com","name":"xkeith"}],"readme":"---\ntitle: IceForm\ncategory: Components\nchinese: 表单组件\n---\n\n表单组件\n\n## 参数（Props）\n\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| initialValues |  表单初始值    |  N    |   object   |    {}    |   -   |\n| onSubmit |  submit函数   |  Y    |   function   |    -    |   -   |\n| onChange |  表单变化回调   |  N    |   function   |    -    |   function(values: object, item: object) => void <br> 参数: <br> values: {object} 表单数据 <br> item: {object} 详细 <br> item.name: {string} 变化的组件名 <br> item.value: {string} 变化的数据 |\n| rules |  校验规则   |  N    |   object   |    {}    |   -   |\n| effects |  联动规则   |  N    |   array   |    []    |   -   |\n| layout |  表单布局   |  N    |   object   |      |   -   |\n| renderField |  自定义 Field 布局   |  N    |   function   |   -   |   function({label, component, error}) => dom  <br> 参数: <br> label: {string/element} Field 的 label <br> component: {string/function} 待渲染的控件 <br> error: {string/element} Field 错误提示信息  |\n\n其他属性比如 `style`、`className` 等均会传递到 `form` 标签上。\n\n`layout` 是个对象，包含 4 个属性：\n\n```js\n{\n  labelAlign: 'left',       // label 的位置，'left'、'top'，默认 'left'\n  labelTextAlign: 'right',  // label 文字对齐方式，'left'、'right'，默认 'right'\n  labelCol: 1,             // label 占的栅格宽度，共 12 等分，默认 2\n  wrapperCol: 3,           // 控件占的栅格宽度，共 12 等分，默认 6\n}\n```\n\n`rules` 是一个 Object，`key` 是 `<Field>` 的 `name` 属性值，`value` 是个数组，数组里面的每一项是一个校验规则，参考 [async-validator](https://github.com/yiminghe/async-validator)。\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  style={{color: '#ee7893'}}\n  rules={{\n    username: [{\n      required: true,\n      min: 5,\n      message: '姓名至少5个字符'\n    }],\n    age:  [{\n      required: true,\n      message: '年龄必填'\n    }]\n  }}\n>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n</Form>\n```\n\n`effects` 是个数组，写法如下：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n  effects={[\n    {\n      field: 'username',\n      handler: formCore => {\n        if (formCore.getFieldValue('username') === 'ice') {\n          formCore.setFieldValue('age', 2)\n        }\n      }\n    }\n  ]}\n>\n  <div>Hello Form</div>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n监听该 `field` 的 `onChange` 事件，然后设置其他表单项的数据，从而达到联动效果。`handler` 的参数是 `formCore` 对象，该对象暴露一些 api 可以设置 value、error、show/hide 等。\n\n## Field 组件\n\n| 参数名 | 说明 | 必填 | 类型 | 默认值 | 备注 |\n| ------ | ---- | ---- | ---- | ------ | ---- |\n| label |  表单项的 label    |  N    |   string/element   |    -    |   -   |\n| name |  表单项的 name   |  Y    |   string   |    -    |   -   |\n| component |  表单类型，原生 html 标签或者三方组件   |  N    |  string/function   |    -    | 'input' 'textarea' Input Radio   |\n| value |  表单项的值    |  N    |  -  |    ''    |   -   |\n| rules |  校验规则   |  N    |   object or array   |    -    |   -   |\n| effects |  联动规则   |  N    |   object   |    -    |   -   |\n| visible |  显示隐藏当前 Field   |  N    |   boolean   |  true  |   true/false  |\n| setValueFormatter |  格式化控件渲染值  |  N    |   function   |    |  function(savedValue) => renderValue  |\n| getValueFormatter |  格式化控件提交值  |  N    |   function   |    |  function(renderValue) => savedValue  |\n| layout |  设置当前 Field 的布局   |  N    |   object   |   同 Form layout   |  当前 Field 的 layout 会覆盖 Form 的 layout |\n| tips |  提示信息   |  N    |   string   |    |    |\n| valueName |  控件值的名称，比如，radio 的 valueName 为 'checked'，value 为 true/false  |  N    |   string   |    |  比如 Fusion 的 Switch 组件  |\n| errorRender |  自定义 error 渲染   |  N    |   function(error) {}   |    |   |\n| onChange |  自定义 onChange 函数   |  N    |   function() {}   |    | 默认情况下已处理表单的 onChange(eventOrValue) 事件，如果接入的三方控件 onChange 的第一个参数不是 event 或者 value，可以主动设置对应的值。比如，接入控件的 onChange(xxx, value) 第二个参数才是 value，则可以手动设置 `formCore.setValue(fieldname, value)` |\n\n`style`、`className` 属性会传递到 Field 最外层 dom 上，其他属性会传递到 `component` 上，如果没有 `component` 但有 `children`，则属性传递到 `children` 上。\n\n`Field` 的 `rules` 和 `effects` 不需要 `name` 作为 key 了，写法如下：\n\n```js\n<Form onSubmit={this.onSubmit}>\n  <Field label=\"姓名：\" name=\"username\" component=\"input\" type=\"text\" />\n  <Field label=\"昵称：\" name=\"nickname\" component=\"input\" type=\"text\" effects={{\n    handler: formCore => {\n      if (formCore.getFieldValue('nickname') === 'snow') {\n        formCore.setFieldProps('age', {\n          visible: true,\n        });\n      } else {\n        formCore.setFieldProps('age', {\n          visible: false,\n        });\n      }\n    }\n  }} />\n  <Field label=\"年龄：\" name=\"age\" component='input' type=\"number\" rules={[{\n    required: true,\n    message: '年龄必填'\n  }]} />\n  <button type=\"submit\">Submit</button>\n</Form>\n```\n\n## FieldArray 组件\n\nFieldArray 表示渲染数组类型的数据，属性同 Field：\n\n```js\n<Form\n  onSubmit={this.onSubmit}\n>\n  <FieldArray label=\"新增顾客：\" name=\"customers\">\n    <Field name=\"customer0\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer1\" component={Input} placeholder=\"customer name\" />\n    <Field name=\"customer2\" component={Input} placeholder=\"customer name\" />\n  </FieldArray>\n  <Field label=\"日期：\" name=\"date\" component={DatePicker} />\n  <Field label=\"\">\n    <Button htmlType=\"submit\">Submit</Button>\n  </Field>\n</Form>\n```\n\n## `formCore` API\n\n`formCore` 会暴露一些 API，使用这些 API 可以获取、设置表单的数据、状态等。\n\n- `getFieldValue(name)`：获取某一 `Field` 的值\n- `setFieldValue(name, value)`：设置某一 `Field` 的值\n- `getValues()`：获取表单的 values\n- `setValues(values, runEffects)`：设置表单的 values，runEffects 为 Boolean，表示设置 values 之后是否需要执行表单的 effects，默认 false\n- `getFieldError(name)`：获取某一 `Field` 的 error 信息\n- `setFieldError(name, errMsg)`：设置某一 `Field` 的 error 信息\n- `getErrors()`：获取所有 `Field` 的 error 信息\n- `setErrors(errors)`：设置某些 `Field` 的 error 信息\n- `getFieldProps(name)`：获取某一 `Field` 的属性值\n- `setFieldProps(name, prop)`：设置某一 `Field` 的属性值\n- `submit()`：提交表单\n- `reset(initialValues)`：重置表单值为表单初始化时的默认值，如果表单初始化时没有默认值，则清空表单；如果传了参数 initialValues，则 initialValues 会成为新的表单默认值\n\n也可以通过属性的方式获取到一些数据：\n\n- `formCore.values`：获取表单的所有值\n- `formCore.errors`：获取表单校验的错误信息\n- `formCore.pristine`：表单当前的 `values` 是否与 `initialValues` 相等\n\n## 延伸阅读\n\n### 开发 @ice/form 表单背景\n\n对于前端，表单开发是一件特别繁琐的事情，尤其在中后台业务中，大家常常会被各种五花八门的表单折磨，又不得不面对现实地去寻找最佳方案，但最终都会发现过度设计的表单组件性能不好，使用简单的表单组件还是需要写大量的业务代码。经过长期的积累以及在社区的调研，我们开发了一个表单组件帮助大家快速地创建一个高性能表单。\n\n### 组件特性\n\n- 内部几乎无依赖，体积小\n- 内部管理表单状态，提升开发效率\n- 使用观察者模式提升表单性能\n- 强大的校验以及声明式联动\n- 可结合第三方组件库(Next、Antd)\n- 可自定义 Field\n\n### 架构方案\n\n![](https://img.alicdn.com/tfs/TB1gFAvaUGF3KVjSZFoXXbmpFXa-1024-768.jpg)\n\n如上图所示，整个表单的数据都放在 FormCore 这一层，同时 FormCore 会暴露一些 API，以便获取、设置、处理数据。Form、Field 组件通过 Sub/Pub 模式与 FormCore 通信，FormCore 通知组件何时重新渲染。表单提供了校验、联动以及结合 Fusion、Antd 三方组件库使用等能力。\n\n### 竞品对比\n\n**[NoForm](https://github.com/alibaba/nopage)**\n\nNoForm 是一个表单操作(比如说校验、提交、联动等)抽象到上层，下层又包装了 Next、Antd 等组件，UI 上的能力较强，也封装了一些常用的布局，但功能能力较弱，用户实现复杂逻辑还是需要写很多代码。\n\n**[Formik](https://github.com/jaredpalmer/formik)**、**[react-final-form](https://github.com/final-form/react-final-form)**\n\n这两个组件有一些共性，都是通过 render props 的方式实现了复杂的状态管理，在性能上也非常地卓越，在社区得到了大量的好评，但在联动上的能力较弱(目前只能更新 value)，而且如果要集成 Next 或者 Antd 需要将库的表单组件都封装成 Field，成本较高。\n\n### 相关链接\n\n- [formik](https://github.com/jaredpalmer/formik)\n- [react-final-form](https://github.com/final-form/react-final-form)\n- [noform](https://alibaba.github.io/nopage/#/nopage/noform/brief-intro)","readmeFilename":"README.md"}