前言
这些年做react,深受form使用麻烦的苦,最后发现动态配置化表单是form使用的正确姿势,高效,易读,易维护。
结合自己的工作经验,花了一个多星期手写了一版 form的二次封装。
二次封装最难的是方案设计和实现,样式是最简单的了,每个公司样式需求各不同,本次封装就不涉及样式了,只专注功能实现。
核心源码行数不多,如果有兴趣,直接去github上,下载源码看看,下面有连接。
默认用法
这种用法使用enform提供的默认样式。
默认从上到下排列。默认表单超过8个field会进行分栏;你也可以自定设置每列显示的field数目。
在config.js中设置好:
1 2 3 4 5
| <EnForm title="动态表单" config={formConfig} onSubmit={onSubmit} />
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| import CustomInput from './component/CustomInput'; const formConfig = { fields: [ { name: 'editname', defaultValue: 'test', title: 'edit user name', Render: CustomInput, validate: [ [(value, formValue) => { if (String(value).length > String(formValue.region).length) { return 'hellow region'; } return ''; }, ['region']] ], required: 'this is required' }, { name: 'region', title: 'region', type: 'input', defaultValue: '', required: true } ], };
export default formConfig;
|
点击查看详细demo
自由排列
如果你既想配置化生成表单,又想自由排列field的位置,又想在form表单中插入任意内容,也是非常方便的,
这也是Enform的亮点了,
EnForm.EnField
中定义的name 要与 config.js中的name一致从而保持一种映射关系。
同时定义layoutMode="custom"
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <EnForm title="登录" config={formConfig} onSubmit={onSubmit} layoutMode="custom" > <div > <div> <div> 随意排列,任意写入内容 </div> <div> <EnForm.EnField className="form-cell" name="editname" /> </div> </div> </div> <p>hellow world</p> <EnForm.EnField className="form-cell" name="useName" /> <div className="region"> <div>任意位置</div> <EnForm.EnField className="form-cell" name="region" /> <div>自由放置</div> <EnForm.EnField className="form-cell" name="passWord" /> </div> <EnForm.EnField className="form-cell" name="select" /> </EnForm>
|
点击查看详细demo
联动
如果组件间需要联系,设置起来也是非常方便的, 在config.js中,将联动组件定义为自定义组件,每个自定义组件都将获得修改form三要素 form value, form validate error msgs, form field display 的能力:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| const formConfig = { fields: [ { name: 'editname', defaultValue: 'test', title: 'edit user name', Render: CustomInput, validate: [ [(value, formValue) => { if (String(value).length > String(formValue.region).length) { return 'hellow region'; } return ''; }, ['region']] ], required: 'this is required' }, ], };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| export default (props) => { const { value, onChange: propsOnChange, setDisplay, setErrMsgs } = props; const getNewFormValue = (value, field, {formValue})=>{ return { ...formValue, [field.name]: value, passWord:`${value} - custom set` } } const onChange = (e) => { propsOnChange(e.target.value, getNewFormValue); };
const [text, setText] = useState('hide')
const onClick = ()=>{ setText(text === 'hide'? 'show': 'hide'); setDisplay((formDisplay)=> { const deleteStatus = _.get(formDisplay, 'passWord.delete'); return {...formDisplay, passWord:{...formDisplay.passWord, delete: !deleteStatus}}; }) } return ( <> <input value={value} onChange={onChange} /> <span onClick={onClick}>{text} password</span> </> ); }
|
设计方案
设计方案博客 - EnForm动态表单封装
源码
源码/demo github