- 作者:老汪软件技巧
- 发表时间:2024-10-08 10:11
- 浏览量:
如何基于 Ant Design 创建动态表单?关于 Ant Design 上传组件 的入门教程关于 Ant Design 选择组件 的入门教程关于 Ant Design 中单行多列表单布局教程
只要你有需要展示表格数据的需求,那必然离不开操作 组件。Ant Design 中所提供的 组件功能非常丰富,只在一篇文章中是无法覆盖的,本篇只定位它的基础使用。
基础使用
组件,至少要传入 3 个 prop,才能正常展示:一个是 dataSource,一个是 columns,还有一个 rowKey。
import { Table } from 'antd'
function App() {
return (
<Table
dataSource={dataSource}
columns={columns}
/>
)
}
假设,我们要展示的数据如下:
const dataSource = [
{
id: '1',
name: '胡彦斌',
age: 32,
address: '西湖区湖底公园1号',
},
{
id: '2',
name: '胡彦祖',
age: 42,
address: '西湖区湖底公园2号',
},
];
那么,表格的 rowKey 就可以设置成具有唯一含义的 id 字段:
<Table
dataSource={dataSource}
columns={columns}
rowKey="id"
/>
当然,rowKey 还可以是一个函数,接受当前行数据为参数,可以让你自定义 rowKey 取值的逻辑。比如:rowKey={(record) => record.login.uuid}
接下来,表格需要展示“姓名”、“年龄”和“住址”这 3 个字段,那么我们就可以这样定义 columns。
const columns = [
{
title: '姓名',
dataIndex: 'name',
},
{
title: '年龄',
dataIndex: 'age',
},
{
title: '住址',
dataIndex: 'address',
},
];
title 表格列名,dataIndex 则表示列名所对应的字段名,有这 2 个就够了。
查看效果:
可以数据被正确渲染出来了。其中,表格各个列默认自动布局,这得益于底层 元素 table-layout: auto; 的设置。
同时,你还能看到右下角还有一个分页标记。没错, 组件还自带了分页展示支持(通过 Pagination 组件)!这一块内容后续我们会细讲,先忽略。
以上,我们就完成了一个表格数据的基础展示案例。
当然,在项目代码中,你可能还会看到设置 columns 使用了 key 字段,这个 key 通常又是跟 dataIndex 是一样的值。
const columns = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
},
];
说起来,这个 key 其实是在渲染 组件时使用 React key,保证数据刷新时的正确渲染。
不过, 在内部渲染时,帮我们做了一个优化——如果我们已经设置了 dataIndex,那么 key 默认就等于该值,是可以忽略不去设置的。
自定义字段渲染
当然,我们有时面临的渲染场景比较负责,提供的字段仅通过简单的字段渲染是做不到 UI 要求的效果的。
比如,下面的数据:
const data = [
{
id: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
id: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['loser'],
},
{
id: '3',
name: 'Joe Black',
age: 32,
address: 'Sydney No. 1 Lake Park',
tags: ['cool', 'teacher'],
},
];
在渲染时,我们需要对 tags 字段做特殊样式的展示处理,如下所示。
这里,就需要借助标签组件 。
那么 columns 该怎么写呢?前两个比较简单,我们参照上面的案例写出来。
const columns = [
{
title: 'Age',
dataIndex: 'age',
},
{
title: 'Address',
dataIndex: 'address',
},
// ...
]
到了标签这一块,单纯的 dataIndex 是满足不了展示需求的,这个时候就要用到 **render** prop 来自定义渲染样式了。
我们先来看看 render 函数的定义:
render 函数接受 3 个参数:
text:即表示当前渲染的字段值record:则表示当前渲染行的值index:表示当前渲染行的值的索引
那么这就比较好写了:
import { Table, Tag } from 'antd'
const columns = [
// ...
{
title: 'Tags',
dataIndex: 'tags',
render: (tags) => (
<>
{tags.map((tag) => {
return (
<Tag key={tag}>
{tag.toUpperCase()}
Tag>
);
})}
>
)
}
]
当然,render 中的渲染还可以更加丰富:
import { Table, Tag } from 'antd'
const columns = [
// ...
{
title: 'Tags',
dataIndex: 'tags',
render: (tags) => (
<>
{tags.map((tag) => {
let color = tag.length > 5 ? 'geekblue' : 'green';
if (tag === 'loser') {
color = 'volcano';
}
return (
<Tag color={color} key={tag}>
{tag.toUpperCase()}
Tag>
);
})}
>
)
}
]
最终,展示效果如下:
当然,在自定义渲染时,你可能还会遇到渲染其他一些带有操作行为的字段。
比如下面的 Name 和 Action。
那么就可以这样定义:
const columns = [
{
title: 'Name',
dataIndex: 'name',
render: (name) => <a>{name}a>,
},
// ...
{
title: 'Action',
key: 'action',
render: (_, { name }) => (
<Space size="middle">
<a>Invite {name}a>
<a>Deletea>
Space>
),
},
]
以上每个 都表示一个操作,可能是个链接跳转,也可能是一次接口请求。限于篇幅,就不具体写实现逻辑了。
注意,最后的 Action 字段,由于并不没有实际对应字段,因此没有设置 dataIndex,但为了更新时的正确渲染,我们设置了 key。
字段排序和过滤
还有 2 个常见的场景,就是进行字段排序和过滤。
排序
先说排序,就要用到 sorter prop。
const columns = [
{
title: 'Name',
dataIndex: 'name',
+ sorter: (a, b) => a.name.localeCompare(b.name),
render: (name) => {name},
},
// ...
}
sorter prop 是一个排序函数,类似 array.sort() 方法的 compareFunction 参数,这里我们是针对姓名做的排序的,使用的是字符串的 localeCompare() 方法。
设置好后,就能看到字段名右侧出现一个排序标志,如此便开启了排序支持。hover 上去时会有提示,点击就可以进行相应排序。
先是升序(asc),后者是降序(desc),排序中的列会有激活样式效果。
针对年龄的排序同理:
{
title: 'Age',
+ sorter: (a, b) => a.age - b.age,
dataIndex: 'age',
},
查看效果:
当然,你还可以通过设置 sortDirections prop 设置所支持的排序方式,其默认值是 ['ascend', 'descend'],我们改成 ['ascend'],表示只需要支持升序即可:
{
title: 'Age',
sorter: (a, b) => a.age - b.age,
+ sortDirections: ['ascend'],
dataIndex: 'age',
},
再来看效果:
目前年龄就只支持升序排序了。
过滤
再来说说字段过滤。要先实现过滤效果,需要在 column 上的两个 prop 搭配使用:filters 和 onFilter。
const columns = [
// ...
{
title: 'Address',
dataIndex: 'address',
filters: [
{
text: 'London',
value: 'London',
},
{
text: 'New York',
value: 'New York',
},
],
onFilter: (value, record) => record.address.startsWith(value),
},
// ...
]
看看效果:
我们勾选一个选项“London”,点击“OK”,就得到过滤后的结果:
不止如此,对于更加负责的数据结构筛选,filters 也通过 children 来支持:
const columns = [
// ...
{
title: 'Address',
dataIndex: 'address',
filters: [
{
text: 'London',
value: 'London',
},
{
text: 'New York',
value: 'New York',
children: [
{
text: 'Green',
value: 'Green',
},
{
text: 'Black',
value: 'Black',
},
],
},
],
onFilter: (value, record) => {
console.log('>>>> [onFilter] value: ', value)
return record.address.startsWith(value)
},
},
// ...
]
效果如下:
这样,就在“New York”之下分离出了“Green”和“Black”2 个子筛选项。筛选后效果:
不过这种情况下,“New York”就无法选中了,这个时候就可以设置 filterMode: 'tree'(默认值 'menu')。
const columns = [
// ...
{
title: 'Address',
dataIndex: 'address',
+ filterMode: 'tree',
filters: [/* ... */]
},
// ...
]
再来看看效果:
筛选后效果:
可以看到当选择“New York”之后,最终过滤时,过滤条件是包括“New York”本身在内的所有子条件的并集。
渲染分组表头
接下来,再介绍一下关于 UI 层面的一个设置——渲染分组表头,类似下面这样:
不过,我们这里渲染会比较简单,只要改动点就是把 Name 拆分成 FirstName 和 LastName 进行展示:
为了能够实现上述的分组表头展示,我们需要调整下数据源——将 name 字段拆分成 firstName 和 lastName。
const data = [
{
id: '1',
firstName: 'John',
lastName: 'Brown',
age: 32,
address: 'New York No. 1 Lake Park',
tags: ['nice', 'developer'],
},
{
id: '2',
firstName: 'Jim',
lastName: 'Green',
age: 42,
address: 'London No. 1 Lake Park',
tags: ['loser'],
},
{
id: '3',
firstName: 'Joe',
lastName: 'Black',
age: 32,
address: 'Sydney No. 1 Lake Park',
tags: ['cool', 'teacher'],
},
];
为了实现分组表头,就要用到 column 里的 children 字段:
const columns = [
{
title: 'Name',
key: 'name',
children: [
{
title: 'First Name',
dataIndex: 'firstName',
},
{
title: 'Last Name',
dataIndex: 'lastName',
}
]
},
// ...
]
最终效果如下:
我们再给表格添加边线样式,默认是没有边线效果:
+ bordered
dataSource={data}
columns={columns}
rowKey="id"
/>
再来看看效果:
固定列
对于列数很多的表格,通常需要固定列,横向滚动查看其它数据。在 Ant Design 中,可以通过 fixed prop 来实现(可取值:'left' 和 'right'),不过还要设置 scroll.x/y 配合使用,否则不能生效。
const columns = [
// ...
{
title: 'Action',
key: 'action',
+ fixed: 'right',
render: (_, { name }) => (
Invite {name}
Delete
),
},
]
return (
+ scroll={{ x: 1200 }}
/>
)
效果如下:
其次,你能看到 scroll={{ x: 1200 }} 的设置最终作用到了 元素上。
首先,为了让固定列起作用首先将 table-layout 设置成 fixed,其次设置了 width: 1200px。
当然,我们还可以设置 scroll.y 来限制表格高度:
- scroll={{ x: 1200 }}
+ scroll={{ x: 1200, y: 120 }}
/>
效果如下:
scroll.y 反馈到表格内容的包装元素 .ant-table-body 之上,最终反馈为 max-height: 120px。
最后,为了 UI 体验上的提升,默认 table-layout: fixed 之后的表格的列都是等宽的。这通常不是最优的,这个时候可以通过为每列设置 width 来提升体验:
const columns = [
{
title: 'Name',
key: 'name',
children: [
{
title: 'First Name',
dataIndex: 'firstName',
+ width: 120,
},
{
title: 'Last Name',
dataIndex: 'lastName',
+ width: 120,
}
]
},
{
title: 'Age',
+ width: 80,
},
{
title: 'Address',
+ width: 220,
// ...
},
{
title: 'Tags',
+ width: 200,
// ...
},
{
title: 'Action',
+ width: 220,
// ...
},
]
效果如下:
可展示行
当表格内容较多不能一次性完全展示时,可以使用展开列的能力。
以下,我们重新声明 data 和 columns。
const data = [
{
id: 1,
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
description: 'My name is John Brown, I am 32 years old, living in New York No. 1 Lake Park.',
},
{
id: 2,
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
description: 'My name is Jim Green, I am 42 years old, living in London No. 1 Lake Park.',
},
{
id: 3,
name: 'Not Expandable',
age: 29,
address: 'Jiangsu No. 1 Lake Park',
description: 'This not expandable',
},
{
id: 4,
name: 'Joe Black',
age: 32,
address: 'Sydney No. 1 Lake Park',
description: 'My name is Joe Black, I am 32 years old, living in Sydney No. 1 Lake Park.',
},
];
每条数据的 description 属性都是其数据的补充内容,点开时展开。
columns 如下所示:
const columns = [
{ title: 'Name', dataIndex: 'name', key: 'name' },
{ title: 'Age', dataIndex: 'age', key: 'age' },
{ title: 'Address', dataIndex: 'address', key: 'address' },
{
title: 'Action',
key: 'action',
render: () => <a>Deletea>,
},
]
中通过 prop 来设置展开行为。其主要有 2 个分关键子属性:expandedRowRender 和 rowExpandable。
+ expandable={{
+ expandedRowRender: (record) => {record.description}
,
+ rowExpandable: (record) => record.name !== 'Not Expandable',
+ }}
/>
效果如下:
每行左侧都会出现一个 + 号,点击即可查看展开内容:
总结
本文,我们总结了 Ant Design 表格组件 的基础使用。主题涉及基本使用、自定义字段渲染、字段排序和筛选、分组表头渲染、固定列和可展示行,基本涵盖了表格的所有基本使用场景。
希望对你的工作能有所帮助,感谢阅读,再见。