效果
codepen 预览地址 合并多个单元格 el-table
完整 代码
<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')
原理
主要是原始的tableData表格数据
经过处理后,
在tableData 数据 需要合并的项插入 tableOptions 属性
tableOptions 属性中包含了需要合并的表格列项列表columnIndexList 及判断 prop名称 proName
然后 使用 合并行或列的计算方法:span-method="objectSpanMethod"
objectSpanMethod 通过判断 tableOptions 实现合并列