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 />);

猜你喜欢

转载自blog.csdn.net/weixin_44174211/article/details/129393506