Table组件: ant.design/components/...
一、Table
1.rowKey
rowKey 是Table组件的一个必选属性,用于唯一标识表格中的每一行数据。它可以是字符串也可以是一个函数。
作用
性能优化
React通过唯一key来识别组件的变化。当表格的数据更新时,Ant Design会根据rowKey来判断哪些行发生了变化,从而只重新渲染需要更新的行,而不是整个表格。这一点大大提高了渲染效率。
状态管理
在表格的各种交互场景中,像分页、排序、筛选、选择等,rowKey用于跟踪和维护每行数据的状态。 如:
- 记住哪些行被选中(复选框/单选框)
- 保持展开/折叠行的状态
- 处理行内表单的状态
避免渲染错误
如果没有提供唯一的rowKey,antd会默认使用行索引(index)作为它的key,但是当数据排序、分页或删除时,索引(index)会发生变化,会导致React错误地敷用组件,从而引发渲染异常(状态丢失、DOM错位等)。
如何设置
使用数据中唯一字段
这也是最推荐的方法,即使用数据里已有的唯一ID字段:
js
<Table
dataSource={data}
rowKey="id"
// 假设数据中有唯一的id字段
// 或使用函数形式: rowKey={record => record.id}
/>
自定义生成rowKey
如果数据中没有合适的唯一字段,那么就可以通过组合,进行字段生成:
js
<Table
dataSource={data}
rowKey={record =>`${record.name}-${record.timestamp}`}
// 组合多个字段确保唯一性
/>
唯一字段不止一个
比如有的人有身份证号,但有的人只有护照号,唯一字段不只有一个,那么就可以进行判断:
js
<Table
dataSource={data}
rowKey={record =>record?.idCard|| record?.passportId}
//确保两个字段不会同时存在,或者同时存在时它们的值相同
/>
注意事项
- 必须保证唯一性:也就是同一个表格中不能有重复的rowKey值
- 要避免使用行索引:除非页面是静态的,不会排序、分页、增删等
- 保持稳定性:同一行的rowKey应始终保持不变,即使数据内容发生变化
2. onChange
onChange是antd提供的一个强大的回调函数,用于处理表格的分页、排序、筛选等交互事件。
触发时机
-
分页:
- 切换页码;
- 调整每页显示数量(如果启用了showSizeChanger)
-
排序:
- 点击列表头进行排序
- 切换排序方向(升/降/取消排序)
-
筛选:
- 使用列筛选器进行选择或取消排序
- 清除筛选器

- 树形表格
- 展开/折叠属性表格的节点(树形表格的展开 / 折叠操作默认不会触发
onChange
回调。只有当树形表格的expandedRowKeys
作为受控属性时 ,onChange
才会在展开 / 折叠时被触发。树形表格的展开 / 折叠需要通过专门的回调 处理,即onExpand
)
- 展开/折叠属性表格的节点(树形表格的展开 / 折叠操作默认不会触发
参数详解
onChange接受四个参数:
js
onChange={(pagination, filters, sorter, extra) => {
// 处理变化
}}
pagination 参数
包含当前分页状态的对象,常见属性有:
js
{
current: 1, // 当前页码
pageSize: 10, // 每页显示数量
total: 100, // 数据总条数
pageSizeOptions: ['10', '30', '50'], // 分页大小选项
showSizeChanger: true, // 是否显示分页大小切换器
showQuickJumper: true, // 是否显示快速跳转
showTotal: (total) => `共 ${total} 条` // 显示总数信息
}
filters 参数
包含当前所有筛选条件的对象,格式为:
js
{
[columnKey]: value[]
}
如:
js
{
status: ['active', 'pending'], // 多选项筛选
age: [20, 30], // 范围筛选
gender: ['male'] // 单选项筛选
}
- 注意:
- 筛选值始终是数组,即使是单选的筛选,所选的值也会被包装在数组中(如
['male']
) - 清除筛选后,对应的字段值会为undefined(如
{ status: undefined }
)
sorter 参数
包含当前排序状态的对象,属性有:
js
{
field: 'age', // 排序字段(对应列的dataIndex)
order: 'descend', // 排序顺序('ascend' 或 'descend')
column: { ... }, // 排序的列配置对象
columnKey: 'age' // 列的唯一标识
}
- 未排序状态 :
{ field: undefined, order: undefined }
- 自定义排序函数 :如果列配置中使用了自定义排序函数(如
sorter: (a, b) => a.age - b.age
),可以通过column.sorter
访问
extra 参数(可选)
包含的是触发变化的额外信息,例如:
js
{
action: 'sort', // 触发变化的操作类型('paginate', 'sort', 'filter')
currentDataSource: [...], // 当前表格的数据源
trigger: 'click', // 触发事件的方式(如'click')
node: { ... } // 树形表格中被操作的节点
}
注意事项
1. 受控与非受控模式
-
受控模式 :提供
pagination
属性并通过onChange
更新状态js<Table pagination={pagination} // 受控模式 onChange={onChange} />
-
非受控模式 :不提供
pagination
属性,表格使用内部状态js<Table onChange={onChange} // 非受控模式,仅监听变化 />
2. sorter API VS onChange 中的 sorter
这两者是定义排序规则 和获取排序结果的关系:
sorter
属性(定义排序规则)
在 Table 的列配置中使用,用于指定该列是否可排序及排序逻辑:
js
const columns = [
{
title: '年龄',
dataIndex: 'age',
sorter: true, // 简单数字/字符串排序
// 或自定义排序函数:
sorter: (a, b) => a.age - b.age,
// 或多列排序:
sortDirections: ['ascend', 'descend'],
},
];
onChange
回调中的sorter
参数(获取排序结果)
当用户点击列标题进行排序时,onChange
会被触发,并携带当前的排序状态:
js
<Table
onChange={(pagination, filters, sorter) => {
console.log('当前排序:', sorter);
// 输出示例:
// {
// field: 'age',
// order: 'descend',
// column: { ... }
// }
}}
/>
diff
- 两者的关联
- sorter属性定义了列的排序能力和规则
- onChange回调获取用户实际操作后的排序结果
- 前端排序时,Ant Design 会根据sorter自动处理数据排序
- 后端排序时,需要将onChange中的sorter参数传递给 API
Form
自定义组件:为什么 Form.Item 嵌套子组件后,不更新表单值?
为什么 Form.Item 嵌套子组件后,不更新表单值?
Form.Item 在渲染时会注入 value
与 onChange
事件给子元素,当你的字段组件被包裹时属性将无法传递。所以以下代码是不会生效的:
js
<Form.Item name="input">
<div>
<h3>I am a wrapped Input</h3>
<Input />
</div>
</Form.Item>
可以通过 HOC 自定义组件形式来解决这个问题:
js
const MyInput = (props) => (
<div>
<h3>I am a wrapped Input</h3>
<Input {...props} />
</div>
);
<Form.Item name="input">
<MyInput />
</Form.Item>;