React AntDesign Table 动态合并单元格(大量数据有分页时也有效)

项目场景:

老板要求有相同数据时,那一列就需要合并起来,还能怎么办,硬着 ‘头’ 去实现吧


问题描述:

看了 Ant design官方文档 的旁友可以了解到 单元格 有一个属性 rowSpan, 它的value是数字,数字越大,渲染占据的行数越多,为0时那一个单元格不会渲染,可以看看下方这个不严谨的图

React AntDesign Table 动态合并单元格(大量数据有分页时也有效)

由于本人有点菜鸡,所以动态合并的方法是参考了其他兄弟弄出来的,但是后面发现了个问题,他们的解决方法在有翻页的情况会出现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;
      },
    },
 ]

原因分析:

可能有小伙伴把上面那串代码拿去改造试验了一下,发现可以正常使用,但是如果有分页的话,点击分页这串代码就会出问题了
  1. 当有大量数据时,我们需要对表格做分页处理,减少页面渲染占用以及方便用户浏览
  2. 小伙伴可以仔细看看,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 }),
	      ),
	    }}
	  />)
}

React AntDesign Table 动态合并单元格(大量数据有分页时也有效)
React AntDesign Table 动态合并单元格(大量数据有分页时也有效)


总结

写得可能会有点乱不好意思哈,也只是做个记录,让自己能记得,也给后面遇到的兄弟提供一点思路,对这段代码有优化建议的兄弟也提出来一起学习哈

上一篇:vue-cli+element-ui使用axios


下一篇:Android——通知Notification