本文主要记录本人在使用antd
开发react hooks
项目过程中,遇到的组件使用上的问题记录。总结一句话:多多熟悉官网文档,没有过不去的坎!
内容涉及以下antd
组件:
Form
Select
Table
Pagination
官方文档链接:点击查看 Ant Design 官方文档
一、Form
1. 表单默认值设置问题
Form
表单提供 initialValues
属性可为表单中每一个具体的表单项设置默认值,Form.Item
也提供属性 initialValue
可设置默认值。表单默认值设置优先级高于表单项默认值设置。
<Form
......
initialValues={{
name: 'Mary',
age: 30
}}
>
......
</Form>
但如果是动态新增表单项,如何设置每一个动态新增的表单项的默认值呢?
我第一反应就是使用 Form.Item
提供的属性 initialValue
来设置,这时我发现,结果并不理想,因为在抽屉组件中写的动态表单,然后第一次动态新增完成后,第二次在弹出抽屉新增时,由于设置了 Form.Item
默认值,发现上一次新增的表单项虽然数据清空了,但表单项仍然在,这就很尴尬了!
后来,我又想到用表单的 initialValues
属性来设置默认值,如下
<Form
......
initialValues={{
users: [
{
name: 'Mary',
}
]
}}
>
......
</Form>
得到的结果是,只有默认显示的第一个表单项默认值生效了,后来新增的表单项默认值都没有设置成功。但重置表单后上一次新增的表单项会被重置,那就还剩一个问题,如果设置动态新增的表单项的默认值。
接下来我通过仔细分析动态新增表单的代码,发现在新增动态表单项时,执行了 add
方法,官网案例如下:
<Button
type="dashed"
onClick={() => add()} // 注意这里
block
icon={<PlusOutlined />}
>
Add field
</Button>
如果能在add执行的时候,添加默认值那不就能解决问题了?
于是,我发现了 add
方法确实是支持设置默认值的,只是第一次使用这个组件库没有发现这个细节!!!
<div onClick={() => add({ name: 'Mary', age: 20 })}>
<span>新增</span>
</div>
2. 复杂的动态新增表项问题
antd提供了 Form.List
用于动态新增表单项,但可能和我们之前接触过的动态新增的思维方式有所不同,所以需要花一些时间仔细理解一下。
先上一下官方案例,乍一看,真的不理解…
<Form.List name="users">
// 这里的fields对应下面文档截图中的children的第一个参数,是一个数组,即动态标单项字段数组。此变量名称可以随便自定义
// 第二个参数是动态表单的内部操作operation,包含 add remove move,这里只解构了add和remove方法
// 操作方法支持的入参可具体查看文档,我上面也有截图
{(fields, { add, remove }) => (
<>
// 循环动态表单项字段数组,动态渲染表单项
{fields.map(({ key, name, ...restField }) => (
<Space key={key} style={{ display: 'flex', marginBottom: 8 }} align="baseline">
<Form.Item
{...restField}
name={[name, 'first']} // 注意这里的字段name属性定义
rules={[{ required: true, message: 'Missing first name' }]}
>
<Input placeholder="First Name" />
</Form.Item>
<Form.Item
{...restField}
name={[name, 'last']}
rules={[{ required: true, message: 'Missing last name' }]}
>
<Input placeholder="Last Name" />
</Form.Item>
<MinusCircleOutlined onClick={() => remove(name)} />
</Space>
))}
<Form.Item>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
Add field
</Button>
</Form.Item>
</>
)}
</Form.List>
然后果断看一下官方解释
antd动态新增表单的思想是,把所有动态增删的操作都封装在组件内部,只对外暴露方法,我们可以自由调用方法控制增删表单项的时机。
官方文档在对于各种内置方法的参数解释上,没有过多具体的文字说明,这也增加了大家的理解时间成本,需要大家多多动手实践,以上是我的理解,欢迎大家积极讨论并指出问题!
3. 自定义表单控件问题
Ant Design表单提供自定义表单控件的功能, 我们可以自定义表单组件,然后在子组件内部会默认存在 value 值 和 onChange方法,我们可以通过value获取到父级表单的自定义表单控件赋值,通过onChange方法改变父级表单本控件的表单值
自定义表单组件:
<Form.Item label="自定义表单控件" name="myFormComponent">
<<MyFormComponent />
</Form.Item>
MyFormComponent.tsx:
import React from 'react';
const MyFormComponent: React.FC<MyFormComponentProps> = ({ value, onChange }) => {
const handleOnChange = (currentValue: string[]) => {
onChange?.(currentValue);
};
return (
<Select
value={value}
onChange={handleOnChange}
...
>
// 这里是具体下拉列表数据
</Select>
);
}
自定义表单控件实现之后,我们可以直接调用表单提供的api form.setFieldsValue
控制自定义表单内部的值value数据。相当于自定义表单控件拥有和普通表单组件一样的对 form
方法的支持度。这也是和我们传统自定义组件封装不一样的地方!
二、Select
1. placeholder问题
当 Select 组件的 value
值类型为 string
类型时,如果 value
值为空字符串,placeholder
会出现不显示的问题。
这个时候我们只要将value
处理为 null
或 undefined
placeholder
就会重新显示出来。即 value={value || undefined}
。
一般出现着这种情况都是因为我们的 Select
框需要支持搜索,实时搜索加载远程接口数据。
三、Table
1. 表格列宽度配置问题
Ant Design的Table组件的表头是通过配置 columns
来实现的,我们可以通过在 columns
中增加 width
属性来设置每一列的宽度,但你会发现,当我们的列表项过多的时候,为每一列都设置了宽度之后,由于宽度不够会导致某些宽度设置并不能生效,列表项会出现被挤压的很窄的情况!
其实,解决这个问题也很简单,只需要在表格组件上新增 scroll
属性就可以了,官方对此属性的值也做了详细的说明,但可能很多人都不会注意到这个问题
具体使用代码如下:
<Table
columns={columns}
rowKey="id"
scroll={{ x: 'max-content' }}
...
/>
四、Pagination
1. 事件触发问题
关于分页事件触发问题,我这里只做一个记录提醒大家一下,具体使用还是参考官方文档。
对于 Pagination 官方提供很多API,其中需要注意的是 onChange
和 onShowSizeChange
,注意这两个不能同时使用,为什么呢?
因为根据官方描述,pageSize
变化后这两个事件都会触发,根据测试会发现,onShowSizeChange
会在 onChange
之前触发,如果你同时使用这两个API且在两个事件函数里面都对 pageSize
做了逻辑处理,那么很可能出现逻辑覆盖的情况,增加代码错误率!!!