antd Table 行合并

想实现表格数据相同的行合并

//判断合并数据的行数
 mergeRowSpan = (text, arry, key) => {
    let i = 0;
    arry.forEach(item => {
      item[key] === text ? i++ : ''
    });
    return i;
  };
//表格表头
 const columns = [
      {
        title: '采集器名称',
        dataIndex: 'collector',
        key: 'collector',
        render: value => {
          const obj = {
            children: value,
            props: {},
          };
          obj.props.rowSpan = this.mergeRowSpan(value, dataSource , 'collector');
          return obj;
        },
      },
      {title: '串口', dataIndex: 'b', key: 'b',},
      {title: '仪表地址', dataIndex: 'c', key: 'c'},
      {title: '仪表编号', dataIndex: 'd', key: 'd'},
      {title: '仪表名称', dataIndex: 'e', key: 'e'},
      {title: '通讯状态', dataIndex: 'f', key: 'f'},
      {title: '最后采集时间', dataIndex: 'g', key: 'g'},
      {title: '在线总时长', dataIndex: 'h', key: 'h'},

    ];
//表格数据
 const dataSource = [
      {collector: '1', b: '1', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: '1', b: '1', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: '1', b: '2', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: '1', b: '2', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: '1', b: '3', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
    ];

但结果很奇怪,有什么好的方法吗

clipboard.png

阅读 7.7k
1 个回答

结果不奇怪,是你没理解 rowSpan 是怎么用的。rowSpan 在这里的意义是描述这一列要占多少行。

如果你把数据改成如下,并且把 rowSpan 全部设成5,你就可以看的出来。

 const dataSource = [
      {collector: 'a', b: '1', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: 'b', b: '1', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: 'c', b: '2', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: 'd', b: '2', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: 'e', b: '3', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
    ];

由于第一个把一整列都占据了,把后面的往后推了,所以导致你这个阶梯状的模样。

回到 rowSpan 上来,antd 实现列合并的原理是,当 rowSpan 设为0的时候,这一列就不会显示,然后你把其中一列设置为整个列的高,使它占据一整列,看起来就像是合并了一样。

所以你的算法要实现的是,在连续出现相同的值时,将最后一次出现的项的 rowSpan 赋值为该值出现的次数,然后其它设置为0(其实未必要最后一个,随便一个都可以)。

但是这个算法你会发现,用一次循环是不可能实现的,所以你算 rowSpan 的算法要从 table 的循环渲染里抽离出来,单独计算。而且如果不是连续相同的话,是不可能合在一起的,所以你可能要先排序。

const getRowSpans = (arr, key) => {
    let sameValueLength = 0;
    const rowSpans = [];
    for(let i = arr.length - 1; i >= 0; i--){
        if(i === 0) {
            rowSpans[i] = sameValueLength + 1;
            continue;
        }
        if(arr[i][key] === arr[i-1][key]) {
            rowSpans[i] = 0;
            sameValueLength++;
        } else {
            console.log(sameValueLength)
            rowSpans[i] = sameValueLength + 1;
            sameValueLength = 0;
        }
    }
    return rowSpans;
};

const dataSource = [
      {collector: '1', b: '1', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: '1', b: '1', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: '1', b: '2', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: '1', b: '2', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
      {collector: '1', b: '3', c: '1', d: '1', e: '1', f: '1', g: '1', h: '1'},
    ];

const  rowSpans = getRowSpans(dataSource, 'collector')

console.log(rowSpans);

 const columns = [
      {
        title: '采集器名称',
        dataIndex: 'collector',
        key: 'collector',
        render: (value, _, index) => {
          const obj = {
            children: value,
            props: {},
          };
          
          obj.props.rowSpan = rowSpans[index];
          return obj;
        },
      },
      {title: '串口', dataIndex: 'b', key: 'b',},
      {title: '仪表地址', dataIndex: 'c', key: 'c'},
      {title: '仪表编号', dataIndex: 'd', key: 'd'},
      {title: '仪表名称', dataIndex: 'e', key: 'e'},
      {title: '通讯状态', dataIndex: 'f', key: 'f'},
      {title: '最后采集时间', dataIndex: 'g', key: 'g'},
      {title: '在线总时长', dataIndex: 'h', key: 'h'},

    ];
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题