先看看官网示例
<template>
<Table
:columns="columns"
:data="data"
border
:span-method="handleSpan"
></Table>
</template>
<script>
export default {
data() {
return {
columns: [
{
title: "Date",
key: "date",
},
{
title: "Name",
key: "name",
},
{
title: "Age",
key: "age",
},
{
title: "Address",
key: "address",
},
],
data: [
{
name: "John Brown",
age: 18,
address: "New York No. 1 Lake Park",
date: "2016-10-03",
},
{
name: "Jim Green",
age: 24,
address: "London No. 1 Lake Park",
date: "2016-10-01",
},
{
name: "Joe Black",
age: 30,
address: "Sydney No. 1 Lake Park",
date: "2016-10-02",
},
{
name: "Jon Snow",
age: 26,
address: "Ottawa No. 2 Lake Park",
date: "2016-10-04",
},
],
};
},
methods: {
handleSpan({ row, column, rowIndex, columnIndex }) {
if (rowIndex === 0 && columnIndex === 0) { // 表示的是第一行第一列
return [1, 2]; // 表示合并1行2列
} else if (rowIndex === 0 && columnIndex === 1) { // 表示的是第一行第二列
return [0, 0]; // 表示合并0行0列,即被合并的单元格(注意:被合并到单元格一定要返回[0,0]否则数据会乱套)
}
if (rowIndex === 2 && columnIndex === 0) { // 表示的是第三行第一列
return { // 表示合并2行1列
rowspan: 2,
colspan: 1,
};
} else if (rowIndex === 3 && columnIndex === 0) { // 表示的是第四行第一列
return { // 表示合并0行0列
rowspan: 0,
colspan: 0,
};
}
},
},
};
</script>
主要是设置 span-method
属性可以指定合并行或列的算法。
上面代码示例是根据行号和列号来进行合并判断的,现实情况我们很有可能需要动态判断合并的单元格。
注意:在合并行时,需要合并到数据必须相邻,数据在数组中的下标要紧挨这,否则无法合并。可以自己根据需要将数据排好序后再合并。
假设我们根据name
值相同的合并单元格
效果图:
代码实现:
<template>
<Table
:columns="columns"
:data="data"
border
:span-method="handleSpan"
></Table>
</template>
<script>
export default {
data() {
return {
columns: [
{
title: "Date",
key: "date",
},
{
title: "Name",
key: "name",
},
{
title: "Age",
key: "age",
},
{
title: "Address",
key: "address",
},
],
resData: [
{
id: "1",
name: "John Brown",
age: 18,
address: "New York No. 1 Lake Park",
date: "2016-10-03",
},
{
id: "3",
name: "John Brown",
age: 24,
address: "London No. 1 Lake Park",
date: "2016-10-01",
},
{
id: "2",
name: "Joe Black",
age: 30,
address: "Sydney No. 1 Lake Park",
date: "2016-10-02",
},
{
id: "4",
name: "Jon Snow",
age: 26,
address: "Ottawa No. 2 Lake Park",
date: "2016-10-04",
},
],
data: [],
};
},
methods: {
handleSpan({ row, column, rowIndex, columnIndex }) {
//合并第二列,这里columnIndex===1 根据具体业务来,比如本示例中需要合并的name为第二列
if (columnIndex === 1) {
//计算合并的行数列数
let x = row.mergeCol === 0 ? 0 : row.mergeCol;
let y = row.mergeCol === 0 ? 0 : 1;
return [x, y];
}
},
formatData(data) {
let names = [];
//筛选出不重复的 name值,将其放到 names数组中
data.forEach((e) => {
if (!names.includes(e.name)) {
names.push(e.name);
}
});
let nameNums = [];
//将names数组中的 name值设置默认合并0个单元格,放到 nameNums中
names.forEach((e) => {
nameNums.push({ name: e, num: 0 });
});
//计算每种 name值所在行需要合并的单元格数
data.forEach((e) => {
nameNums.forEach((n) => {
if (e.name === n.name) {
n.num++;
}
});
});
//将计算后的合并单元格数整合到 data中
data.forEach((e) => {
nameNums.forEach((n) => {
if (e.name === n.name) {
if (names.includes(e.name)) {
e.mergeCol = n.num;
//删除已经设置过的值(防止被合并的单元格进到这个 if 语句中)
names.splice(names.indexOf(n.name), 1);
} else {
//被合并的单元格设置为 0
e.mergeCol = 0;
}
}
});
});
//将整理后的数据交给表格渲染
return data;
},
},
mounted() {
this.data = this.formatData(this.resData);
},
};
</script>
什么意思,意思就是比如我先合并了name
列中相同的行,如果name
列已经合并的行中还有相同的age
列需要合并的话,应该怎么做?
数据预处理:先排序,把相同的
name
值放到一起,然后再把相同的age
放到一起
<template>
<Table
class="border-table"
:columns="columns"
:data="data"
border
:span-method="handleSpan"
></Table>
</template>
<script>
export default {
data() {
return {
columns: [
{
title: "Date",
key: "date",
},
{
title: "Name",
key: "name",
},
{
title: "Age",
key: "age",
},
{
title: "Address",
key: "address",
},
],
resData: [
{
id: "1",
name: "John Brown",
age: 18,
address: "New York No. 1 Lake Park",
date: "2016-10-03",
},
{
id: "3",
name: "John Brown",
age: 24,
address: "London No. 1 Lake Park",
date: "2016-10-01",
},
{
id: "5",
name: "John Brown",
age: 24,
address: "London No. 2 Lake Park",
date: "2016-10-03",
},
{
id: "2",
name: "Joe Black",
age: 30,
address: "Sydney No. 1 Lake Park",
date: "2016-10-02",
},
{
id: "4",
name: "Jon Snow",
age: 26,
address: "Ottawa No. 2 Lake Park",
date: "2016-10-04",
},
],
data: [],
};
},
methods: {
handleSpan({ row, column, rowIndex, columnIndex }) {
//合并第二列,这里columnIndex===1 根据具体业务来,比如本示例中需要合并的name为第二列
if (columnIndex === 1) {
//计算合并的行数列数
let x = row.mergeCol === 0 ? 0 : row.mergeCol;
let y = row.mergeCol === 0 ? 0 : 1;
return [x, y];
}
// age 合并
if (columnIndex === 2) {
//计算合并的行数列数
let x = row.mergeColAge === 0 ? 0 : row.mergeColAge;
let y = row.mergeColAge === 0 ? 0 : 1;
return [x, y];
}
},
formatData(data) {
// 根据 name 排序 age
for (let i = 0; i < data.length - 1; i++) {
for (let n = i + 1; n < data.length; n++) {
if (data[i].age > data[n].age) {
[data[i], data[n]] = [data[n], data[i]];
}
}
}
let names = [];
//筛选出不重复的 name值,将其放到 names数组中
data.forEach((e) => {
if (!names.includes(e.name)) {
names.push(e.name);
}
});
let nameNums = [];
//将names数组中的 name值设置默认合并0个单元格,放到 nameNums中
names.forEach((e) => {
nameNums.push({ name: e, num: 0 });
});
//计算每种 name值所在行需要合并的单元格数
data.forEach((e) => {
nameNums.forEach((n) => {
if (e.name === n.name) {
n.num++;
}
});
});
//将计算后的合并单元格数整合到 data中
data.forEach((e) => {
nameNums.forEach((n) => {
if (e.name === n.name) {
if (names.includes(e.name)) {
e.mergeCol = n.num;
//删除已经设置过的值(防止被合并的单元格进到这个 if 语句中)
names.splice(names.indexOf(n.name), 1);
} else {
//被合并的单元格设置为 0
e.mergeCol = 0;
}
}
});
});
//不唯一且重复的情况下,在唯一的基础上合并重复
for (let j = 0; j < data.length; j++) {
// > 1 name 表示 有合并需要在name合并的row中 再合并
if (data[j].mergeCol > 1) {
for (let k = 0; k < data[j].mergeCol; k++) {
//age合并
if (data[j + k].ageAlready !== 1) { // 需要这个条件,避免数据重复
if (k + 1 < data[j].mergeCol) {
data[j + k].mergeColAge = 1
for (let b = k + 1; b < data[j].mergeCol; b++) {
if (data[j + k].age === data[j + b].age) {
data[j + k].mergeColAge++;
data[j + b].mergeColAge = 0;
data[j + b].ageAlready = 1;
} else {
break;
}
}
}
}
}
}
// 如果有需要在age合并到row中 再合并的话代码添加到此处
}
//将整理后的数据交给表格渲染
return data;
},
},
mounted() {
this.data = this.formatData(this.resData);
},
};
</script>