项目场景:
老板要求有相同数据时,那一列就需要合并起来,还能怎么办,硬着 ‘头’ 去实现吧
问题描述:
看了 Ant design官方文档 的旁友可以了解到 单元格 有一个属性 rowSpan, 它的value是数字,数字越大,渲染占据的行数越多,为0时那一个单元格不会渲染,可以看看下方这个不严谨的图
由于本人有点菜鸡,所以动态合并的方法是参考了其他兄弟弄出来的,但是后面发现了个问题,他们的解决方法在有翻页的情况会出现BUG,或者是他们接收到后台的数据跟我的不一样,所以才有了这篇文章
最开始的方法是通过跟接收到的数据直接进行匹配,然后再对rowSpan进行设置
state = {
data: [], // 表格数据
};
columns = [
{
title: '服务器',
dataIndex: 'server_name',
render: (value, record, index) => {
// 处理列,相同数据则合并
const { data } = this.state;
// 处理rowSpan
const obj = {
children: value,
props: { rowSpan: 1 },
};
// 当检索到相同数据则返回 那条数据
let arr = data.filter((res) => {
return res.server_name == record.server_name;
});
if (index == 0 || data[index - 1].server_name != record.server_name) {
// 匹配到相同数据的长度
obj.props.rowSpan = arr.length;
} else {
// 如果上一行的数据与当前的数据相同,就将rowSpan变为0
obj.props.rowSpan = 0;
}
return obj;
},
},
]
原因分析:
可能有小伙伴把上面那串代码拿去改造试验了一下,发现可以正常使用,但是如果有分页的话,点击分页这串代码就会出问题了- 当有大量数据时,我们需要对表格做分页处理,减少页面渲染占用以及方便用户浏览
- 小伙伴可以仔细看看,state 中的 data,这个是保存接收到的数据,再来看看下面的这串代码
/**
* 这串代码没有考虑到分页的情况,一页有20条数据,第一页是显示[0,20]的数据
* 第二页是显示[21,40]的数据,下面这串代码没有处理这种结果,那就会出现第二页的时候匹配[0,40]的数据
* 结果就会出现表格列错位的情况,这肯定不是我们要的
*/
let arr = data.filter((res) => {
return res.server_name == record.server_name;
});
解决方案:
考虑到有分页的话,我是将分页的数据给用上,获取分页当前的页数,以及每页总共有多少条数据,然后对 data 进行截取,第一页我就截取[0,20]的数据,第二页时我就截取[21,40]的数据,这样的话就不会出现切换分页表格列错位的情况,代码的话提供个大概
state = {
data: [], // 表格数据
page: 1, // 当前页
pageSize: 20, // 页数据条数
};
columns = [
{
title: '服务器',
dataIndex: 'server_name',
render: (value, record, index) => {
// 处理列,相同数据则合并
const { data, page, pageSize } = this.state;
// 截取当前页的数据(主要就这一段)
const start = page * pageSize - pageSize;
const end = data.length > pageSize * page ? data.length - 1 : pageSize * page;
// 截取后的数据
const dealData = data.slice(start, end);
// 处理rowSpan
const obj = {
children: value,
props: { rowSpan: 1 },
};
// 当检索到相同数据则返回
let arr = dealData.filter((res) => {
return res.server_name == record.server_name;
});
if (index == 0 || dealData[index - 1].server_name != record.server_name) {
obj.props.rowSpan = arr.length;
} else {
obj.props.rowSpan = 0;
}
return obj;
},
},
]
render() {
return (
<table
columns={this.columns}
pagination={{
pageSizeOptions: ['20', '50', '100', '200', '500'],
// 当页数或单页总条数改变时,就更新一下state
onChange: (page, pageSize) => this.setState({ page, pageSize }),
),
}}
/>)
}
总结
写得可能会有点乱不好意思哈,也只是做个记录,让自己能记得,也给后面遇到的兄弟提供一点思路,对这段代码有优化建议的兄弟也提出来一起学习哈