参考
-
- 只适合单列
- 多列的话,改造难度大,可能需要每条数据维护一个数组才行
多列合并实现(有序)
-
只支持要合并的列已排好序的情况
-
效果
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 />);