合并单元格 element-ui + vue
效果图
1.不统计,不考虑前一项
在mounted中使用 this.merge(false,false,this.needMerge)
2.统计,不考虑前一项
在mounted中使用 this.merge(false,true,this.needMerge)
3.统计,考虑前一项
在mounted中使用 this.merge(true,true,this.needMerge)
4.不统计,考虑前一项
在mounted中使用 this.merge(true,false,this.needMerge)
5.合并stack、share项
修改needMerge为 [‘stack’,‘share’]
代码
<template>
<el-table class="tableList" :data="dataSource" border stripe :span-method="objectSpanMethods" style="width:80%" :default-sort = "{prop: 'className'}">
<el-table-column v-for="col in columns" :prop="col.prop" :key="col.id" :label="col.label" :min-width="col.width">
</el-table-column>
</el-table>
</template>
<script>
// 表格数据
const dataSource = [
{id:1,className:'物联网1班',stack:'java',sex:'男',share:'80'},
{id:1,className:'物联网1班',stack:'java',sex:'女',share:'20'},
{id:2,className:'物联网1班',stack:'vue',sex:'男',share:'90'},
{id:3,className:'物联网1班',stack:'vue',sex:'女',share:'10'},
{id:4,className:'物联网1班',stack:'php',sex:'男',share:'95'},
{id:5,className:'物联网1班',stack:'php',sex:'女',share:'5'},
{id:6,className:'物联网2班',stack:'java',sex:'男',share:'90'},
{id:7,className:'物联网2班',stack:'java',sex:'女',share:'10'},
{id:8,className:'物联网3班',stack:'vue',sex:'男',share:'20'},
{id:9,className:'物联网3班',stack:'vue',sex:'男',share:'80'},
{id:10,className:'物联网3班',stack:'java',sex:'女',share:'50'},
{id:11,className:'物联网3班',stack:'java',sex:'男',share:'50'}
]
// 表格列
const columns = [
{label:'班级',prop:'className',width:'auto'},
{label:'技术栈',prop:'stack',width:'auto'},
{label:'性别',prop:'sex',width:'auto'},
{label:'占有率',prop:'share',width:'auto'}
]
// 所有的列名
const columnCollections = ['className', 'stack','sex','share']
// 需要合并的列
const needMerge = ['className', 'stack','sex','share']
// 数据为排好序的数据。合并表格相同的列,table为要进行比较的数组,columnCollections为要比较的所有属性的集合,isPrev表示是否需要考虑前一列在合并
function mergeTheSameRow(table, columnCollections,isPrev) {
// 对应列项合并数据的数组
let arrCol = []
// 指针数组,记录当前在哪一列
let posList = []
// 初始化
for(let i = 0 ; i < columnCollections.length ; i++){
arrCol.push([])
posList.push(0)
}
for (var i = 0; i < table.length; i++) {
if (i === 0) {
for(let j = 0 ; j < columnCollections.length ; j++){
arrCol[j].push(1)
posList[j] = 0
}
} else {
let isSame =true
for(let j = 0 ; j < columnCollections.length ; j++){
isPrev? '' : isSame = true
isSame = isSame && table[i][columnCollections[j]] === table[i - 1][columnCollections[j]]
if(isSame){
arrCol[j][posList[j]] += 1
arrCol[j].push(0)
}else{
arrCol[j].push(1)
posList[j] = i
}
}
}
}
return arrCol;
}
export default {
data(){
return {
dataSource: dataSource,
columns:columns,
spanObj: {},
// 需要合并的列项
columnCollections:columnCollections,
needMerge:needMerge
}
},
methods:{
objectSpanMethods({ row, column, rowIndex, columnIndex }) {
for(let i = 0 ; i < this.columnCollections.length ; i++ ){
if (columnIndex === i && this.needMerge.includes(this.columnCollections[i])) {
const _row2 = this.spanObj[this.columnCollections[i]][rowIndex];
const _col2 = _row2 > 0 ? 1 : 0;
return {
rowspan: _row2,
colspan: _col2
}
}
}
},
merge(isPrev = true,isCensus = false,needMerge){
// 得到需要合并的数据
let returnTableResult = mergeTheSameRow(this.dataSource, this.columnCollections ,isPrev );
needMerge.forEach(items=>{
let index = this.columnCollections.findIndex(item=>item==items)
if(index > -1){
this.spanObj[this.columnCollections[index]] = returnTableResult[index]
}
})
// 是否需要统计总数
if(isCensus){
this.$nextTick(()=>{
this.dataSource.forEach((item,index)=>{
for(let i = 0 ; i < this.columnCollections.length ; i++){
if(needMerge.includes(this.columnCollections[i])){
item[this.columnCollections[i]] += `(${returnTableResult[i][index]})`
}
}
})
})
}
}
},
mounted(){
//第一个参数代表是否需要考虑前一列相同在考虑后面的
//第二个参数代表是否需要统计数据
//第三个代表需要合并列的字段
this.merge(false,false,this.needMerge)
}
}
</script>
<style lang="less" scoped>
.tableList{
.table-head-box{
display: flex;
.el-icon-d-caret{
margin-left: 10px;
cursor: pointer;
}
.el-icon-caret-bottom{
margin-left: 10px;
cursor: pointer;
}
}
}
</style>