el-table合并单元格

1.固定合并

  • 官方挺提供的合并具体某行列的方法:el-table合并行或列
  • 通过给table传入span-method方法可以实现合并行或列,方法的参数是一个对象,里面包含当前行row、当前列column、当前行号rowIndex、当前列号columnIndex四个属性。
    该函数可以返回一个包含两个元素的数组,第一个元素代表rowspan,第二个元素代表colspan。 也可以返回一个键名为rowspancolspan的对象。
<template><div><el-table:data="tableData":span-method="arraySpanMethod"borderstyle="width: 100%"><el-table-columnprop="id"label="ID"width="180"></el-table-column><el-table-columnprop="name"label="姓名"></el-table-column><el-table-columnprop="amount1"sortablelabel="数值 1"></el-table-column><el-table-columnprop="amount2"sortablelabel="数值 2"></el-table-column><el-table-columnprop="amount3"sortablelabel="数值 3"></el-table-column></el-table><el-table:data="tableData":span-method="objectSpanMethod"borderstyle="width: 100%; margin-top: 20px"><el-table-columnprop="id"label="ID"width="180"></el-table-column><el-table-columnprop="name"label="姓名"></el-table-column><el-table-columnprop="amount1"label="数值 1(元)"></el-table-column><el-table-columnprop="amount2"label="数值 2(元)"></el-table-column><el-table-columnprop="amount3"label="数值 3(元)"></el-table-column></el-table></div></template><script>export default {data() {return {tableData: [{id: '12987122',name: '王小虎',amount1: '234',amount2: '3.2',amount3: 10}, {id: '12987123',name: '王小虎',amount1: '165',amount2: '4.43',amount3: 12}, {id: '12987124',name: '王小虎',amount1: '324',amount2: '1.9',amount3: 9}, {id: '12987125',name: '王小虎',amount1: '621',amount2: '2.2',amount3: 17}, {id: '12987126',name: '王小虎',amount1: '539',amount2: '4.1',amount3: 15}]};},methods: {arraySpanMethod({ row, column, rowIndex, columnIndex }) {if (rowIndex % 2 === 0) {if (columnIndex === 0) {return [1, 2];} else if (columnIndex === 1) {return [0, 0];}}},objectSpanMethod({ row, column, rowIndex, columnIndex }) {if (columnIndex === 0) {if (rowIndex % 2 === 0) {return {rowspan: 2,colspan: 1};} else {return {rowspan: 0,colspan: 0};}}}}};</script>

运行效果:

  • 缺点这种只适合写死的数据和固定的表格行列,无法动态判断单元格数据是否相等再合并;

2. 动态合并相同数据单元格(所有列)

  • 可以对所有相同数据的列,进行动态合并
  • 此方法适合需要合并所有的相同数据的单元格
<template><div><el-table:data="tableData":span-method="objectSpanMethod"border :header-cell-style="{ textAlign: 'center', backgroundColor: '#F5F7FA' }"><el-table-column prop="School" label="学校" align="center"></el-table-column><el-table-column prop="Grade" label="年级" align="center" /><el-table-column prop="Class" label="班级" align="center" /><el-table-column prop="Name" label="姓名" align="center" /><el-table-column prop="Chinese" label="语文" align="center" /><el-table-column prop="Math" label="数学" align="center" /><el-table-column prop="English" label="英语" align="center" /></el-table></div></template><script>export default {data() {return {// 存放所有的表头 一定要与tableData一致colFields: ["School","Grade","Class","Name","Chinese","Math","English",],spanArr: [], //存储合并单元格的开始位置// 表格数据tableData: [// 一年级{School: "第一小学",Grade: "1年级",Class: "1班",Name: "张三",Chinese: "90",Math: "100",English: "80",},{School: "第一小学",Grade: "1年级",Class: "2班",Name: "李四",Chinese: "90",Math: "85",English: "80",},{School: "第一小学",Grade: "1年级",Class: "3班",Name: "王五",Chinese: "79",Math: "100",English: "80",},// 二年级{School: "第一小学",Grade: "2年级",Class: "1班",Name: "赵六",Chinese: "95",Math: "100",English: "80",},{School: "第一小学",Grade: "2年级",Class: "2班",Name: "钱八",Chinese: "98",Math: "85",English: "80",},{School: "第一小学",Grade: "2年级",Class: "3班",Name: "陈九",Chinese: "79",Math: "100",English: "80",},// 三年级{School: "第一小学",Grade: "3年级",Class: "1班",Name: "黄十",Chinese: "91",Math: "88",English: "80",},{School: "第一小学",Grade: "3年级",Class: "2班",Name: "魏一",Chinese: "90",Math: "86",English: "87",},{School: "第一小学",Grade: "3年级",Class: "3班",Name: "杨二",Chinese: "79",Math: "99",English: "80",},],};},methods: {/** * 分析每一列,找出相同的 * @param data */getSpanArr() {for (let i = 0; i < this.tableData.length; i++) {let row = i;// let col = i % this.colCount;if (row === 0) {// i 表示行 j表示列for (let j = 0; j < this.colFields.length; j++) {this.spanArr[i * this.colFields.length + j] = {rowspan: 1,colspan: 1,};}} else {for (let j = 0; j < this.colFields.length; j++) {// 当前和上一次的一样// 1. 合并所有列的相同数据单元格if (this.tableData[row][this.colFields[j]] ===this.tableData[row - 1][this.colFields[j]]) {let beforeItem =this.spanArr[(row - 1) * this.colFields.length + j];this.spanArr[row * this.colFields.length + j] = {rowspan: 1 + beforeItem.rowspan, // 合并几行colspan: 1, // 合并几列,我这里只是跨行合并,不跨列合并,所以用的1};beforeItem.rowspan = 0;beforeItem.colspan = 0;} else {// rowspan 和 colspan 都为1表格此单元格不合并this.spanArr[row * this.colFields.length + j] = {rowspan: 1,colspan: 1,};}}}}// 对数据进行倒序let stack = [];for (let i = 0; i < this.colFields.length; i++) {for (let j = 0; j < this.tableData.length; j++) {// console.log("i=" + i + " j=" + j);// i 表示列 j表示行if (j === 0) {if (this.spanArr[j * this.colFields.length + i].rowspan === 0) {stack.push(this.spanArr[j * this.colFields.length + i]);}} else {if (this.spanArr[j * this.colFields.length + i].rowspan === 0) {stack.push(this.spanArr[j * this.colFields.length + i]);} else {stack.push(this.spanArr[j * this.colFields.length + i]);while (stack.length > 0) {let pop = stack.pop();let len = stack.length;this.spanArr[(j - len) * this.colFields.length + i] = pop;}}}}}// console.log(this.spanArr);},objectSpanMethod({ row, column, rowIndex, columnIndex }) {// console.log(this.spanArr[rowIndex * this.colFields.length + columnIndex]);return this.spanArr[rowIndex * this.colFields.length + columnIndex];},},mounted() {this.getSpanArr();},};</script><style lang="scss" scoped></style>

效果:

我们可以看到,所有列,只要数据相同的单元格都被合并了,包括我不想合并的单元格,这时候就要指定合并的列

3. 动态合并相同数据单元格(指定列)

  • 只需要加个if判断即可指定要合并哪些列
// 这里只放了部分代码,除了加了个if,其他代码和上面的一样 getSpanArr() {for (let i = 0; i < this.tableData.length; i++) {let row = i;// let col = i % this.colCount;if (row === 0) {// i 表示行 j表示列for (let j = 0; j < this.colFields.length; j++) {this.spanArr[i * this.colFields.length + j] = {rowspan: 1,colspan: 1,};}} else {for (let j = 0; j < this.colFields.length; j++) {// 当前和上一次的一样//合并所有列的相同数据单元格if (this.colFields[j] == "School" ||this.colFields[j] == "Grade" ||this.colFields[j] == "Class") { // 指定合并哪些列if (this.tableData[row][this.colFields[j]] ===this.tableData[row - 1][this.colFields[j]]) {let beforeItem =this.spanArr[(row - 1) * this.colFields.length + j];this.spanArr[row * this.colFields.length + j] = {rowspan: 1 + beforeItem.rowspan,colspan: 1,};beforeItem.rowspan = 0;beforeItem.colspan = 0;} else {// rowspan 和 colspan 都为1表格此单元格不合并this.spanArr[row * this.colFields.length + j] = {rowspan: 1,colspan: 1,};}}}}}

效果:
这样就只合并了我们指定的那几列了

4. 动态合并相同数据单元格(指定列+合并条件)

有时候我们会遇到不想合并的单元格,比如下面这种情况:

按常理来说,不同小学的数据应该是不做合并才对,正确是这种:

这时候就需要加上一些自定义的合并条件了:

getSpanArr() {for (let i = 0; i < this.tableData.length; i++) {let row = i;// let col = i % this.colCount;if (row === 0) {// i 表示行 j表示列for (let j = 0; j < this.colFields.length; j++) {this.spanArr[i * this.colFields.length + j] = {rowspan: 1,colspan: 1,};}} else {for (let j = 0; j < this.colFields.length; j++) {// 当前和上一次的一样//合并所有列的相同数据单元格if (this.colFields[j] == "School" ||this.colFields[j] == "Grade" ||this.colFields[j] == "Class") { // 指定合并哪些列if (this.tableData[row]["School"] !==this.tableData[row - 1]["School"]) { // 哪些不合并:School不一样的,不合并this.spanArr[row * this.colFields.length + j] = {rowspan: 1,colspan: 1,};} else if (this.tableData[row][this.colFields[j]] ===this.tableData[row - 1][this.colFields[j]]) {let beforeItem =this.spanArr[(row - 1) * this.colFields.length + j];this.spanArr[row * this.colFields.length + j] = {rowspan: 1 + beforeItem.rowspan,// 合并几列colspan: 1,// 合并几行};beforeItem.rowspan = 0;beforeItem.colspan = 0;} else {// rowspan 和 colspan 都为1表格此单元格不合并this.spanArr[row * this.colFields.length + j] = {rowspan: 1,colspan: 1,};}}}}}// console.log(this.spanArr);},

这时候再看,就是我们想要的效果了

完整代码

最后附完整代码:

<template><div><el-table:data="tableData":span-method="objectSpanMethod"border:header-cell-style="{ textAlign: 'center', backgroundColor: '#F5F7FA' }"><el-table-column prop="School" label="学校" align="center"></el-table-column><el-table-column prop="Grade" label="年级" align="center" /><el-table-column prop="Class" label="班级" align="center" /><el-table-column prop="Name" label="姓名" align="center" /><el-table-column prop="Chinese" label="语文" align="center" /><el-table-column prop="Math" label="数学" align="center" /><el-table-column prop="English" label="英语" align="center" /></el-table></div></template><script>export default {data() {return {// 存放所有的表头 一定要与tableData一致colFields: ["School","Grade","Class","Name","Chinese","Math","English",],spanArr: [], //存储合并单元格的开始位置// 表格数据tableData: [// 一年级{School: "第一小学",Grade: "1年级",Class: "1班",Name: "张三",Chinese: "90",Math: "100",English: "80",},{School: "第一小学",Grade: "1年级",Class: "1班",Name: "张伟",Chinese: "90",Math: "99",English: "89",},{School: "第一小学",Grade: "1年级",Class: "2班",Name: "李四",Chinese: "90",Math: "85",English: "80",},{School: "第一小学",Grade: "1年级",Class: "3班",Name: "王五",Chinese: "79",Math: "100",English: "80",},// 二年级{School: "第一小学",Grade: "2年级",Class: "1班",Name: "赵六",Chinese: "95",Math: "100",English: "80",},{School: "第一小学",Grade: "2年级",Class: "2班",Name: "钱八",Chinese: "98",Math: "85",English: "80",},{School: "第一小学",Grade: "2年级",Class: "3班",Name: "陈九",Chinese: "79",Math: "100",English: "100",},// 三年级{School: "第一小学",Grade: "3年级",Class: "1班",Name: "黄十",Chinese: "91",Math: "88",English: "80",},{School: "第一小学",Grade: "3年级",Class: "2班",Name: "魏一",Chinese: "90",Math: "86",English: "87",},{School: "第一小学",Grade: "3年级",Class: "3班",Name: "杨二",Chinese: "79",Math: "99",English: "80",},// 第二小学{School: "第二小学",Grade: "3年级",Class: "3班",Name: "袁零",Chinese: "79",Math: "99",English: "80",},],};},methods: {/** * 分析每一列,找出相同的 * @param data */getSpanArr() {for (let i = 0; i < this.tableData.length; i++) {let row = i;// let col = i % this.colCount;if (row === 0) {// i 表示行 j表示列for (let j = 0; j < this.colFields.length; j++) {this.spanArr[i * this.colFields.length + j] = {rowspan: 1,colspan: 1,};}} else {for (let j = 0; j < this.colFields.length; j++) {// 当前和上一次的一样//合并所有列的相同数据单元格if (this.colFields[j] == "School" ||this.colFields[j] == "Grade" ||this.colFields[j] == "Class") { // 指定合并哪些列if (this.tableData[row]["School"] !==this.tableData[row - 1]["School"]) { // 哪些不合并:School不一样的,不合并this.spanArr[row * this.colFields.length + j] = {rowspan: 1,colspan: 1,};} else if (this.tableData[row][this.colFields[j]] ===this.tableData[row - 1][this.colFields[j]]) {let beforeItem =this.spanArr[(row - 1) * this.colFields.length + j];this.spanArr[row * this.colFields.length + j] = {rowspan: 1 + beforeItem.rowspan,// 合并几列colspan: 1,// 合并几行};beforeItem.rowspan = 0;beforeItem.colspan = 0;} else {// rowspan 和 colspan 都为1表格此单元格不合并this.spanArr[row * this.colFields.length + j] = {rowspan: 1,colspan: 1,};}}}}}// 对数据进行倒序let stack = [];for (let i = 0; i < this.colFields.length; i++) {for (let j = 0; j < this.tableData.length; j++) {// console.log("i=" + i + " j=" + j);// i 表示列 j表示行if (j === 0) {if (this.spanArr[j * this.colFields.length + i].rowspan === 0) {stack.push(this.spanArr[j * this.colFields.length + i]);}} else {if (this.spanArr[j * this.colFields.length + i].rowspan === 0) {stack.push(this.spanArr[j * this.colFields.length + i]);} else {stack.push(this.spanArr[j * this.colFields.length + i]);while (stack.length > 0) {let pop = stack.pop();let len = stack.length;this.spanArr[(j - len) * this.colFields.length + i] = pop;}}}}}// console.log(this.spanArr);},objectSpanMethod({ row, column, rowIndex, columnIndex }) {// console.log(this.spanArr[rowIndex * this.colFields.length + columnIndex]);return this.spanArr[rowIndex * this.colFields.length + columnIndex];},},mounted() {this.getSpanArr();},};</script><style lang="scss" scoped></style>

参考:https://blog.csdn.net/u010735120/article/details/122184493