react结合antd的Table组件实现动态单元格合并

首先看一下antd的Table表单组件,合并单元格,用到了rowSpan(合并行)和colSpan(合并列)

 后台返回的数据

[
    {
      key: 0,
      category: '水果',
      name: '桃子',
      desc: '好吃',
    },
    {
      key: 1,
      category: '水果',
      name: '梨子',
      desc: '真好吃',
    },
    {
      key: 2,
      category: '蔬菜',
      name: '茄子',
      desc: '真好吃',
    },
    {
      key: 9,
      category: '蔬菜',
      name: '茄子',
      desc: '真好吃',
    },
    {
      key: 3,
      category: '家禽',
      name: '牛肉',
      desc: '太好吃了',
    },
    {
      key: 4,
      category: '家禽',
      name: '羊肉',
      desc: '真不错',
    },
    {
      key: 5,
      category: '家禽',
      name: '猪肉',
      desc: '吃不起,太贵',
    },
    {
      key: 4,
      category: '家禽',
      name: '羊肉',
      desc: '真不错',
    },
    {
      key: 5,
      category: '家禽',
      name: '猪肉',
      desc: '吃不起,太贵',
    },
  ]

我们希望把category的值相同的,行合并成一个单元格

类似于这种

 rowSpan这个属性可以指定合并行。例如说第一行,指定rowSpan为3,意思就是合并三行,则后面紧挨的两行的rowSpan就需要设置为0。因为他们一共就占有3份,第一行的为3份,已经占完了,下面俩就不能再占了,就必须为0

官网实例中,使用onCell属性,来指定合并多少行/列,onCell的值是一个函数,默认接收2个参数,第一个参数是当前行数据,第二个参数就是这行的索引

我在网上看了一些大佬的做法,感觉直接处理源数据,在源数据中添加它这个所占的份数,直接通过在onCell中指定他所需要合并的行的个数,这种做法最简单

也就是把源数据处理成这种 

[
    {
      key: 0,
      category: '水果',
      name: '桃子',
      desc: '好吃',
      rowSpan: 2,
    },
    {
      key: 1,
      category: '水果',
      name: '梨子',
      desc: '真好吃',
      rowSpan: 0,
    },
    {
      key: 2,
      category: '蔬菜',
      name: '茄子',
      desc: '真好吃',
      rowSpan: 2,
    },
    {
      key: 9,
      category: '蔬菜',
      name: '茄子',
      desc: '真好吃',
      rowSpan: 0,
    },
    {
      key: 3,
      category: '家禽',
      name: '牛肉',
      desc: '太好吃了',
      rowSpan: 3,
    },
    {
      key: 4,
      category: '家禽',
      name: '羊肉',
      desc: '真不错',
      rowSpan: 0,
    },
    {
      key: 5,
      category: '家禽',
      name: '猪肉',
      desc: '吃不起,太贵',
      rowSpan: 0,
    },
    {
      key: 4,
      category: '家禽',
      name: '羊肉',
      desc: '真不错',
      rowSpan: 0,
    },
    {
      key: 5,
      category: '家禽',
      name: '猪肉',
      desc: '吃不起,太贵',
      rowSpan: 0,
    },
  ]

具体代码如下

import { Table } from 'antd'

const Demo1 = () => {
  let field = 'category'
  const data = [
    {
      key: 0,
      category: '水果',
      name: '桃子',
      desc: '好吃',
      // rowSpan: 2,
    },
    {
      key: 1,
      category: '水果',
      name: '梨子',
      desc: '真好吃',
      // rowSpan: 0,
    },
    {
      key: 2,
      category: '蔬菜',
      name: '茄子',
      desc: '真好吃',
      // rowSpan: 2,
    },
    {
      key: 9,
      category: '蔬菜',
      name: '茄子',
      desc: '真好吃',
      // rowSpan: 0,
    },
    {
      key: 3,
      category: '家禽',
      name: '牛肉',
      desc: '太好吃了',
      // rowSpan: 3,
    },
    {
      key: 4,
      category: '家禽',
      name: '羊肉',
      desc: '真不错',
      // rowSpan: 0,
    },
    {
      key: 5,
      category: '家禽',
      name: '猪肉',
      desc: '吃不起,太贵',
      // rowSpan: 0,
    },
    {
      key: 4,
      category: '家禽',
      name: '羊肉',
      desc: '真不错',
      // rowSpan: 0,
    },
    {
      key: 5,
      category: '家禽',
      name: '猪肉',
      desc: '吃不起,太贵',
      // rowSpan: 0,
    },
  ]
  const columns = [
    {
      title: '姓名',
      dataIndex: 'category',
      onCell: (record, index) => {
        // console.log(record.category, record.rowSpan)
        return { rowSpan: record.rowSpan }
      },
    },
    {
      title: '床位',
      // colSpan: 2, // 设置占位2格
      dataIndex: 'parentType',
      /**
       * 每4行都是一个日期,从index = 0 开始,
       * 每隔4行的rowSpan为4,其余的rowSpan为0
       */
      // onCell: (_, index) => ({
      //   rowSpan: index % 2 === 0 || index === 0 ? 2 : 0,
      // }),
    },
    {
      title: '组',
      // colSpan: 0, // 设置占位0格
      dataIndex: 'type',
    },
    {
      title: '药房',
      dataIndex: 'user1',
    },
    {
      title: '类型',
      dataIndex: 'user2',
    },
    {
      title: '项目名称',
      dataIndex: 'user3',
    },
    {
      title: '规格',
      dataIndex: 'user4',
    },
  ]
  const changeData = (data, field) => {
    let count = 0 //重复项的第一项
    let indexCount = 1 //下一项
    while (indexCount < data.length) {
      var item = data.slice(count, count + 1)[0] //获取没有比较的第一个对象
      if (!item.rowSpan) {
        item.rowSpan = 1 //初始化为1
      }
      if (item[field] === data[indexCount][field]) {
        //第一个对象与后面的对象相比,有相同项就累加,并且后面相同项设置为0
        item.rowSpan++
        data[indexCount].rowSpan = 0
      } else {
        count = indexCount
      }
      indexCount++
    }
  }
  changeData(data, field) //处理数据

  return (
    <div>
      <Table
        columns={columns}
        dataSource={data}
        pagination={false}
        bordered
      ></Table>
    </div>
  )
}

export default Demo1

猜你喜欢

转载自blog.csdn.net/qq_52845451/article/details/129112483