Effect
codepen preview address merge multiple cells el-table
full code
<script src="//unpkg.com/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<div id="app">
<template>
<div>
<el-table
:data="tableData"
:span-method="objectSpanMethod"
border
style="width: 100%; margin-top: 20px">
<el-table-column
prop="id"
label="ID"
width="180">
</el-table-column>
<el-table-column
prop="number"
label="号码id">
</el-table-column>
<el-table-column
prop="name"
label="姓名">
</el-table-column>
<el-table-column
prop="amount1"
label="数值 1(元)">
</el-table-column>
<el-table-column
prop="amount2"
label="数值 2(元)">
</el-table-column>
<el-table-column
prop="amount3"
label="数值 3(元)">
</el-table-column>
</el-table>
</div>
</template>
</div>
var Main = {
data() {
return {
storeRowObj:{
},
storeProNameObj:{
},
storeHebingObj:{
},
tableData: [{
id: '1',
name: '王小虎',
amount1: '0',
amount2: '4.1',
amount3: 15,
number:123456,
},{
id: '1',
name: '王小虎',
amount1: '1',
amount2: '4.1',
number:123456,
amount3: 15
},{
id: '1',
name: '王小虎',
amount1: '2',
amount2: '4.1',
amount3: 15,
number:456,
},{
id: '2',
name: '王小虎',
amount1: '3',
amount2: '4.1',
amount3: 15,
number:567,
},{
id: '2',
name: '王小虎',
amount1: '4',
amount2: '4.1',
number:567,
amount3: 15
},{
id: '2',
name: '王小虎',
amount1: '5',
amount2: '4.1',
amount3: 15,
number:789,
},{
id: '2',
name: '王小虎',
amount1: '6',
amount2: '4.1',
number:789,
amount3: 15
},{
id: '3',
name: '王小虎',
amount1: '7',
amount2: '4.1',
number:789,
amount3: 15
},{
id: '3',
name: '王小虎',
amount1: '8',
number:645654465,
amount2: '4.1',
amount3: 15
},{
id: '3',
name: '王小虎',
amount1: '9',
amount2: '4.1',
number:567,
amount3: 15
},{
id: '3',
name: '王小虎',
amount1: '10',
amount2: '4.1',
amount3: 15,
number:789,
},{
id: '3',
name: '王小虎',
amount1: '11',
amount2: '4.1',
number:789,
amount3: 15
},{
id: '3',
name: '王小虎',
amount1: '12',
amount2: '4.1',
number:789,
amount3: 15
},{
id: '3',
name: '王小虎',
amount1: '13',
number:645654465,
amount2: '4.1',
amount3: 15
},{
id: '3',
name: '王小虎',
amount1: '13',
number:'',
amount2: '4.1',
amount3: 15
},{
id: '3',
name: '王小虎',
amount1: '13',
number:'645654465',
amount2: '6',
amount3: 15
},{
id: '3',
name: '王小虎',
amount1: '13',
number:645654465,
amount2: '4.1',
amount3: 15
},
{
id: '3',
name: '王小虎',
amount1: '13',
number:645654465,
amount2: '4.1',
amount3: 15
},
{
id: '3',
name: '王小虎',
amount1: '13',
number:645654468,
amount2: '4.1',
amount3: 15
},]
};
},
created(){
let options = {
//合并顺序必须 优先级从高往低排列
hebingProps: [
{
proName: 'id',
columnIndexList: [0]
},
{
proName: 'number',
columnIndexList: [1,2]
},
{
proName: 'amount2',
columnIndexList: [4]
},
{
proName: 'amount3',
columnIndexList: [5]
}
]
};
this.tableData = this.disposalData(this.tableData,options)
},
methods: {
// 判断是否为空
isEmpty(value){
if(String(value)=='0'){
return true;
}
if(!value){
return false
}
return true;
},
// 判断上一个 proName 的值 是否相等
previousOneProNameValueAllEquality(hebingProps,currentProName,currentItem,storeItem){
if(!storeItem){
return true;
}
let previousProName = null;
for(let i=0;i<hebingProps.length;i++){
let item = hebingProps[i];
if(item.proName==currentProName){
break;
}
previousProName = item.proName;
}
// console.log(previousProName,currentProName);
if(previousProName){
let otherProNameList = [previousProName];
let isEquality = true;
for(let i=0;i<otherProNameList.length;i++){
let key = otherProNameList[i];
if(currentItem[key]!=storeItem[key]){
isEquality = false;
break;
}
}
return isEquality;
}
return true;
},
// 判断之前的proName 是否全部相等
previousProNameValueAllEquality(hebingProps,currentProName,currentItem,storeItem){
if(!storeItem){
return true;
}
let otherProNameList =[];
let proNameIndex = -1;
otherProNameList= hebingProps.filter((item,index)=>{
if(item.proName==currentProName){
proNameIndex = index;
}
if(proNameIndex==-1){
return true;
}
else if(proNameIndex==0 || index >= proNameIndex){
return false;
}
return true;
}).map(item=>item.proName);
if(!otherProNameList.length){
return true;
}
let isEquality = true;
for(let i=0;i<otherProNameList.length;i++){
let key = otherProNameList[i];
if(currentItem[key]!=storeItem[key]){
isEquality = false;
break;
}
}
return isEquality;
},
//整理需要合并的表格数据
/**
options ={
//需要合并的参数
hebingProps: [
{
proName: 'id', //需要合并的prop 名称
columnIndexList: [0] // //需要合并的 columnIndex下标列表
},
]
}
*/
disposalData(list, options = {
}) {
options.hebingProps.forEach((oItem) => {
let {
proName,
columnIndexList
} = oItem;
let storeValue, storeIndex,storePreItem,hebing;
list.forEach((item, index) => {
// let isEquality = this.previousOneProNameValueAllEquality(options.hebingProps,proName,item,storePreItem);
let isEquality = this.previousProNameValueAllEquality(options.hebingProps,proName,item,storePreItem);
if (storeValue != item[proName] || !isEquality) {
if (index != 0) {
let currentItem = list[storeIndex];
if(hebing>1){
let objs = {
[proName]: {
hebing,
proName,
columnIndexList
}
}
if (!currentItem.tableOptions) {
currentItem.tableOptions = {
...objs
}
} else {
currentItem.tableOptions = {
...currentItem.tableOptions,
...objs
}
}
}
}
storeValue = item[proName];
storeIndex = index;
hebing = 1;
} else if (storeValue == item[proName] && this.isEmpty(item[proName]) && index != 0 && isEquality ) {
hebing += 1;
if(index*1+1==list.length){
let currentItem = list[storeIndex];
if(hebing>1){
let objs = {
[proName]: {
hebing,
proName,
columnIndexList
}
}
if (!currentItem.tableOptions) {
currentItem.tableOptions = {
...objs
}
} else {
currentItem.tableOptions = {
...currentItem.tableOptions,
...objs
}
}
}
}
}
storePreItem = item;
})
})
return list
},
objectSpanMethod({
row,
column,
rowIndex,
columnIndex
}) {
let {
tableOptions
} = row;
if (tableOptions) {
for (let key in tableOptions) {
let item = tableOptions[key];
let {
hebing = 0, columnIndexList = [], proName = ''
} = item;
if (columnIndexList.length && columnIndexList.includes(columnIndex)) {
// let hebing = row.hebing || null
if (hebing) {
let storeProName = proName;
this.storeProNameObj[proName] = true;
this.storeRowObj[storeProName + columnIndex] = rowIndex;
this.storeHebingObj[storeProName + columnIndex] = hebing
return {
rowspan: hebing,
colspan: 1,
}
}
}
}
}
for(let key in this.storeProNameObj){
let storeProName = key
let storeRowIndex = this.storeRowObj[storeProName + columnIndex]
let hebing = this.storeHebingObj[storeProName + columnIndex];
if (storeProName && storeRowIndex != undefined &&
storeRowIndex + hebing > rowIndex) {
return {
rowspan: 0,
colspan: 0,
}
}
}
}
}
};
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
principle
Mainly the original tableData table data
After processing,
the items that need to be merged in the tableData data are inserted into the tableOptions attribute. The
tableOptions attribute contains the table column item list columnIndexList that needs to be merged and the judgment prop name proName.
Then use the calculation method of merging rows or columns :span-method="objectSpanMethod"
objectSpanMethod to pass Judging tableOptions to achieve merged columns