开头
前端开发中,如果你使用的是react框架去做开发,不可避免的会与AntDesign这个UI框架打交道。同时在很多实际业务开发中,常用到的当属Form和Table组件,特别是在管理系统这类项目中。前几天,笔者在解决公司项目的一个小bug时,刚好碰到了一个需要Form.Item嵌套来解决的问题。
问题🙋
测试提了一个bug需求,一个input输入框的数值回显的功能没有实现,查看代码时,一开始没有注意之前代码设计思路是formItem的表单值绑定给input的value,因此通过把input的defaultValue设置为productName的值,这个办法当然也是可以解决的。但是,不符合了之前代码的架构。
// 原代码
<Form.Item
label=“Product Name”
name="productName"
initialValue={undefined}
rules={[{ required: true, message: “Please Input”}
>
<div style={{ display: 'flex', alignItems: 'center' }}>
<Input
style={{
width: 240,
flex: 1,
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
}}
disabled={readOnly}
placeholder= “Please Input”
/>
{i18nLanguageBizDicts.length > 1 && (
<Tooltip placement="top" title=“Multilingual”>
<MoreButton
onClick={() => {
if (!readOnly) {
setVisible(true);
}
}}
disabled={readOnly}
style={{
cursor: 'pointer',
borderLeft: '0',
}}
/>
</Tooltip>
)}
</div>
</Form.Item>
尝试
发现是input和另一个组件由于样式的需求,外面包裹了一个div,导致了外层的form.Item没有直接包裹到input组件,因此input没有绑定表单 此时想到了Fragment可以把多个元素整合返回一个元素,且不会影响样式,就使用了React.Fragment去对input和另一个组件进行包裹,结果还是没有解决这个问题。应该是Fragment只整合第一层的元素,因此在查看元素时input外层还是div,于是form.Item与input还是不是直接父子组件,没有绑定。去除div但Fragment上没有style属性,因此放弃这个想法💡
解决🤓
在antd的官方文档可查阅到关于复杂控件(如需要对input/select添加文字描述或其他组件)的使用需要进行form.item的嵌套使用
图源来自antd官方文档
可以理解为,外层form.item是用于控制样式,内层form.item直接包裹组件用于解决数据绑定,因此对于form.item与包裹组件有关的属性值,需要写在内层的form.item属性上。同时,内层的form.item需要设置noStyle为true,这样不会对样式产生影响。
最后实现如下
<Form.Item label={t('Product Name')}>
<div style={{ display: 'flex', alignItems: 'center' }}>
<Form.Item
name="productName"
initialValue={undefined}
noStyle
rules={[{ required: true, message: t('Please input') }]}
>
<Input
style={{
width: 240,
flex: 1,
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
}}
disabled={readOnly}
placeholder={t('Please input')}
/>
</Form.Item>
...
可以发现外层的form.item确实不参与数据传递和绑定,他包裹的直接子元素是div;内层的form.item设置name,rule等值参与input等数据绑定。
结语
在对formItem组件实现input或者其他组件的数据绑定,遇到非直接包裹关系,可以使用嵌套的formItem方案来解决。
入门前端小白第一次写文章,如有不足,恳请大家批评指正!感谢🙏🙏