react + ant design 实现动态合并Table表格(相同数据合并为一条、支持多列)

参考

多列合并实现(有序)

  • 只支持要合并的列已排好序的情况

  • 效果
    在这里插入图片描述

const { createRoot } = ReactDOM;
const { Table } = antd;

const sharedOnCell2 = (record, index, colIndex) => {
  // console.log("data", data);
  // console.log("record", record);
  let dataIndexs = columns.map((o) => o.dataIndex);
  console.log("dataIndexs:" + dataIndexs);

  // 获取数据源中,与当前单元格数据一致的记录,包括自己,只有自己,则 rowSpan=1,刚刚好 
  let arr = data.filter((res) => {
    // return res.name == record.name;
    return getValues(res, colIndex) == getValues(record, colIndex);
  });
  let rowSpan = 1;
  // if (index == 0 || data[index - 1].name != record.name) {
  if (
    index == 0 ||
    getValues(data[index - 1], colIndex) != getValues(record, colIndex)
  ) {
    // 第一行 || 与上一行数据不相等
    rowSpan = arr.length;
  } else {
    // 0表示单元格不会渲染,即不显示,被合并的单元格设为0
    // 不需要合并的单元格还是要显示,所以不能设为0,可以设为空或者1
    rowSpan = 0;
  }
  return { rowSpan: rowSpan };
};

// 获取单元格用来比较的值
// 因为是否合并需要依赖前面的列,所以不能单纯的取值,需要将前面单元格的值也拼接在前面
const getValues = (record, colIndex) => {
  // console.log("getValues--record", record);
  let dataIndexs = columns.map((o) => o.dataIndex);
  console.log("dataIndexs:" + dataIndexs);
  let str = "";
  for (let i = 0; i <= colIndex; i++) {
    // 加一个特殊的连接符,避免2个单元格分开不一样、但合起来变一样的情况
    str += record[dataIndexs[i]] + "@@@";
  }
  return str;
};

const data = [
  {
    key: "1",
    name: "John Brown",
    age: 32,
    tel: "0571-22098909",
    phone: 18889898989,
    address: "New York No. 1 Lake Park"
  },
  {
    key: "1",
    name: "John Brown",
    tel: "0571-22098333",
    phone: 18889898888,
    age: 32,
    address: "London No. 1 Lake Park"
  },
  {
    key: "1",
    name: "John Brown2",
    age: 32,
    tel: "0575-22098909",
    phone: 18900010002,
    address: "Sydney No. 1 Lake Park"
  },
  {
    key: "4",
    name: "Jim Red",
    age: 18,
    tel: "0575-22098909",
    phone: 18900010002,
    address: "London No. 2 Lake Park"
  },
  {
    key: "4",
    name: "Jim Red",
    age: 18,
    tel: "0575-22098909",
    phone: 18900010002,
    address: "Dublin No. 2 Lake Park"
  }
];

const columns = [
  {
    title: "RowHead",
    dataIndex: "key",
    rowScope: "row",
    onCell: (record, index) => {
      return sharedOnCell2(record, index, 0);
    }
  },
  {
    title: "Name",
    dataIndex: "name",
    onCell: (record, index) => {
      return sharedOnCell2(record, index, 1);
    }
  },
  {
    title: "Age",
    dataIndex: "age",
    onCell: (record, index) => {
      return sharedOnCell2(record, index, 2);
    }
  },
  {
    title: "Home phone",
    colSpan: 2,
    dataIndex: "tel"
  },
  {
    title: "Phone",
    colSpan: 0,
    dataIndex: "phone"
  },
  {
    title: "Address",
    dataIndex: "address"
  }
];

const App = () => <Table columns={columns} dataSource={data} bordered />;
const ComponentDemo = App;

createRoot(mountNode).render(<ComponentDemo />);

多列合并实现(无序、空值选择合并或不合并)

const { createRoot } = ReactDOM;
const { Table } = antd;

const sharedOnCell2 = (record, index, colIndex) => {
  //console.log("data", data);
  //console.log("record", record);
  //let dataIndexs = columns.map((o) => o.dataIndex);
  //console.log("dataIndexs:" + dataIndexs);

  // 处理数据未排好序的情况
  let arr = data.filter((res,i) => {
    // return res.name == record.name;
    res.i = i;
    // 空值不合并 赋id或是uuid
    return getValues(res, colIndex, i) == getValues(record, colIndex, index);
    // 空值合并
    // return getValues(res, colIndex, null) == getValues(record, colIndex, null);
  });
  console.log('iiiii:', arr[0])
  // 自己是肯定存在的
  if (arr.length > 1) {
    // 保证序号连续,并且自己存在
    // 上一个
    let pre = arr[0]
    let arr2 = [arr[0]]
    // 自己是否出现
    let b = arr[0].i == index ? true : false;
    for (let i = 1; i < arr.length; i++) {
       // 当前
       let cur = arr[i];
       if ((cur.i - 1) != pre.i) {
         // 不相等 断续
         if (b) {
           break;
         } else {
           arr2 = []
         }
       }
      
       // b = arr[0].i == index ? true : b;
       b = arr[i].i == index ? true : b;
      
       arr2.push(cur)
       pre = cur;
    }
    arr = arr2;
    
  }
  console.log('arrarr:', arr)
  
  let rowSpan = 1;
  // if (index == 0 || data[index - 1].name != record.name) {
  if (
    index == 0 ||
    getValues(data[index - 1], colIndex, index - 1) != getValues(record, colIndex, index)
    // getValues(data[index - 1], colIndex, null) != getValues(record, colIndex, null)
  ) {
    rowSpan = arr.length;
  } else {
    rowSpan = 0;
  }
  return { rowSpan: rowSpan };
};

// 传index 则空值不合并,不传,空值合并
const getValues = (record, colIndex, index) => {
  // console.log("getValues--record", record);
  let dataIndexs = columns.map((o) => o.dataIndex);
  console.log("dataIndexs:" + dataIndexs);
  let str = "";
  for (let i = 0; i <= colIndex; i++) {
    let str1 = record[dataIndexs[i]];
    str1 = str1 ? str1 : (index ? (index + "!@#") : "");
    str += str1 + "@@@";
  }
  return str;
};

const data = [
  {
    key: "1",
    name: "John Brown",
    age: 32,
    tel: "0571-22098909",
    phone: 18889898989,
    address: "New York No. 1 Lake Park"
  },
  {
    key: "1",
    name: "John Brown2",
    tel: "0571-22098333",
    phone: 18889898888,
    age: 32,
    address: "London No. 1 Lake Park"
  },
  {
    key: "1",
    name: "John Brown2",
    age: 32,
    tel: "0575-22098909",
    phone: 18900010002,
    address: "Sydney No. 1 Lake Park"
  },
  {
    key: "4",
    name: "John Brown",
    age: 18,
    tel: "0575-22098909",
    phone: 18900010002,
    address: "London No. 2 Lake Park"
  },
  {
    key: "4",
    name: "John Brown",
    age: 18,
    tel: "0575-22098909",
    phone: 18900010002,
    address: "Dublin No. 2 Lake Park"
  }
  
  {
    key: "1",
    name: null,
    age: 32,
    tel: "0575-22098909",
    phone: 18900010002,
    address: "Sydney No. 1 Lake Park"
  },
  {
    key: "4",
    name: null,
    age: 18,
    tel: "0575-22098909",
    phone: 18900010002,
    address: "London No. 2 Lake Park"
  },
  {
    key: "4",
    name: null,
    age: 18,
    tel: "0575-22098909",
    phone: 18900010002,
    address: "London No. 2 Lake Park"
  },
  {
    key: "4",
    name: "John Brown",
    age: 18,
    tel: "0575-22098909",
    phone: 18900010002,
    address: "Dublin No. 2 Lake Park"
  },
  {
    key: "4",
    name: "John Brown",
    age: 18,
    tel: "0575-22098909",
    phone: 18900010002,
    address: "Dublin No. 2 Lake Park"
  }

];

const columns = [
  {
    title: "RowHead",
    dataIndex: "key",
    rowScope: "row",
    onCell: (record, index) => {
      return sharedOnCell2(record, index, 0);
    }
  },
  {
    title: "Name",
    dataIndex: "name",
    onCell: (record, index) => {
      return sharedOnCell2(record, index, 1);
    }
  },
  {
    title: "Age",
    dataIndex: "age",
    onCell: (record, index) => {
      return sharedOnCell2(record, index, 2);
    }
  },
  {
    title: "Home phone",
    colSpan: 2,
    dataIndex: "tel"
  },
  {
    title: "Phone",
    colSpan: 0,
    dataIndex: "phone"
  },
  {
    title: "Address",
    dataIndex: "address"
  }
];

const App = () => <Table columns={columns} dataSource={data} bordered />;
const ComponentDemo = App;

createRoot(mountNode).render(<ComponentDemo />);

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的实现示例: ```javascript import React from "react"; import { Table } from "antd"; const columns1 = [ { title: "姓名", dataIndex: "name", key: "name" }, { title: "年龄", dataIndex: "age", key: "age" }, { title: "住址", dataIndex: "address", key: "address" }, ]; const data1 = [ { key: "1", name: "John Brown", age: 32, address: "New York No. 1 Lake Park" }, { key: "2", name: "Jim Green", age: 42, address: "London No. 1 Lake Park" }, { key: "3", name: "Joe Black", age: 32, address: "Sidney No. 1 Lake Park" }, ]; const columns2 = [ { title: "科目", dataIndex: "subject", key: "subject" }, { title: "绩", dataIndex: "score", key: "score" }, ]; const data2 = [ { key: "1", subject: "数学", score: 90 }, { key: "2", subject: "英语", score: 80 }, { key: "3", subject: "语文", score: 95 }, ]; const expandedRowRender = (record) => { const subTableData = [ { key: "1", subject: "数学", score: 90 }, { key: "2", subject: "英语", score: 80 }, { key: "3", subject: "语文", score: 95 }, ]; const subTableColumns = [ { title: "科目", dataIndex: "subject", key: "subject" }, { title: "绩", dataIndex: "score", key: "score" }, ]; return <Table columns={subTableColumns} dataSource={subTableData} pagination={false} />; }; const TableWithNestedTable = () => { return ( <Table columns={columns1} dataSource={data1} pagination={false} expandedRowRender={expandedRowRender} /> ); }; export default TableWithNestedTable; ``` 首先,我们先定义两个表格的列和数据,分别为 `columns1` 和 `data1`,以及嵌套的表格的列和数据,分别为 `columns2` 和 `data2`。 然后,我们定义一个 `expandedRowRender` 函数,该函数接受一个参数 `record`,表示当前行的数据。在该函数中,我们返回一个嵌套的表格,该表格的列和数据为 `columns2` 和 `data2`。 最后,我们在主表格中添加 `expandedRowRender` 属性,并将其设置为 `expandedRowRender` 函数,这样就可以实现表格嵌套两层表格的效果了。 注意,我们在嵌套的表格中将 `pagination` 属性设置为 `false`,以禁用分页功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值