1.效果图如下:
2.html 代码:
// html代码:
<template>
<div>
<el-table border ref="table" :data="dataList" style="width: 100%"
:span-method="objectSpanMethod" :header-cell-style="{background:'#FAFAFA'}">
<el-table-column prop="class" label="班级" width="200" align="center"></el-table-column>
<el-table-column prop="sex" label="性别" width="200" align="center"></el-table-column>
<el-table-column prop="age" label="年龄" width="200" align="center"></el-table-column>
<el-table-column prop="hobby" label="爱好" width="200" align="center"></el-table-column>
<el-table-column prop="name" label="姓名" width="200" align="center"></el-table-column>
<el-table-column prop="id" label="id"></el-table-column>
</el-table>
</div>
</template>
3.javascrpit 代码:
// 计算代码
<script>
export default {
name: 'ModuleIndex',
data() {
return {
dataList: [] // 当前展示的数据
}
},
mounted() {
this.init()
},
methods: {
/**
element-table合并单元格的函数
columnIndex 值表示要合并的列的下标,当前示例是合并前4列。
如果你是要合并多列,需要添加对应的列号进行判断,并且添加对应的计算方法,
和对应的计算合并列的方法。
*/
objectSpanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
return this.ret(row, 'firstSpan')
} else if (columnIndex === 1) {
return this.ret(row, 'secondSpan')
} else if (columnIndex === 2) {
return this.ret(row, 'thirdSpan')
} else if (columnIndex === 3) {
return this.ret(row, 'fourthSpan')
}
},
ret(row, obj) {
if (row && row[obj] != 0) {
return {
rowspan: row[obj],
colspan: 1
}
} else {
return {
rowspan: 0,
colspan: 0
}
}
},
// 计算第一列合并总数
computeFirstSpan(firstObj, secondObj, thirdObj, fourthObj) {
// 遍历计算第一列合并行数
for (let obj in firstObj) {
let fristData = this.dataList.filter(d => d.id === firstObj[obj][0])[0]
// 获取第一条数据,对其添加 'firstSpan' 属性,并设置值
if (fristData) fristData['firstSpan'] = firstObj[obj].length
this.computeSecondSpan(firstObj[obj], secondObj, thirdObj, fourthObj)
}
},
// 计算第二列合并总数
computeSecondSpan(classList, secondObj, thirdObj, fourthObj) {
let secondList = []
// 遍历计算第二列合并行数
for (let obj in secondObj) {
// 判断两个id数组,取其并集,并集的长度就是合并列的行数
let secondIds = secondObj[obj].filter(val => {
return classList.indexOf(val) > -1
})
let fristData = this.dataList.filter(d => d.id === secondIds[0])[0]
// 获取第一条数据,对其添加 'secondSpan' 属性,并设置值
if (fristData) fristData['secondSpan'] = secondIds.length
secondList.push(secondIds)
}
secondList.forEach(list => {
this.computeThirdSpan(list, thirdObj, fourthObj)
})
},
// 计算第三列合并总数
computeThirdSpan(list, thirdObj, fourthObj) {
let thirdList = []
// 遍历计算第三列合并行数
for (let obj in thirdObj) {
let thirdIds = thirdObj[obj].filter(val => {
return list.indexOf(val) > -1
})
let fristData = this.dataList.filter(d => d.id === thirdIds[0])[0]
// 获取第一条数据,对其添加 'thirdSpan' 属性,并设置值
if (fristData) fristData['thirdSpan'] = thirdIds.length
thirdList.push(thirdIds)
}
thirdList.forEach(list => {
this.computeFourthSpan(list, fourthObj)
})
},
// 计算第四列合并总数
computeFourthSpan(list, fourthObj) {
// 遍历计算第四列合并行数
for (let obj in fourthObj) {
let fourthIds = fourthObj[obj].filter(val => {
return list.indexOf(val) > -1
})
let fristData = this.dataList.filter(d => d.id === fourthIds[0])[0]
// 获取第一条数据,对其添加 'fourthSpan' 属性,并设置值
if (fristData) fristData['fourthSpan'] = fourthIds.length
}
},
/**
* 构建合并列数据
* 思路:遍历所有数据,将需要合并的列的内容作为key,数据id作为value,然后依次遍历获取对应的合并列的行数
*/
buildMerge(dataList) {
let firstObj = {},
secondObj = {},
thirdObj = {},
fourthObj = {}
let firstObjKey = '',
secondObjKey = '',
thirdObjKey = '',
fourthObjKey = ''
// 本示例合并的前四列,对应的字段分别:class、sex、age、hobby
// 如果你需要合并其他的字段,需修改此处字段名称
for (let i = 0, len = dataList.length; i < len; i++) {
firstObjKey = dataList[i].class
secondObjKey = dataList[i].sex
thirdObjKey = dataList[i].age
fourthObjKey = dataList[i].hobby
if (!firstObj[firstObjKey])
firstObj[firstObjKey] = new Array(dataList[i].id)
else {
firstObj[firstObjKey].push(dataList[i].id)
}
if (!secondObj[secondObjKey])
secondObj[secondObjKey] = new Array(dataList[i].id)
else {
secondObj[secondObjKey].push(dataList[i].id)
}
if (!thirdObj[thirdObjKey])
thirdObj[thirdObjKey] = new Array(dataList[i].id)
else {
thirdObj[thirdObjKey].push(dataList[i].id)
}
if (!fourthObj[fourthObjKey])
fourthObj[fourthObjKey] = new Array(dataList[i].id)
else {
fourthObj[fourthObjKey].push(dataList[i].id)
}
}
this.computeFirstSpan(firstObj, secondObj, thirdObj, fourthObj)
},
// 初始化页面数据
init() {
// 如果是通过接口动态数据时,需要保证每条数据有id,且id唯一
// this.$api.getModuleList().then(res => {
// if (res.body) {
// this.dataList = res.body
// this.dataList.forEach((data, index) => {
// if (!data.id) {
// data['id'] = String(index + 1)
// }
// })
// // debugger
// this.buildMerge(this.dataList)
// }
// })
this.dataList = [
{id: '1', class: '三年级1班', sex: '男', age: '16岁', hobby: '打篮球', name: '张三1'},
{id: '2', class: '三年级1班', sex: '男', age: '16岁', hobby: '打篮球', name: '张三2'},
{id: '3', class: '三年级1班', sex: '男', age: '17岁', hobby: '看书', name: '张三3'},
{id: '6', class: '三年级1班', sex: '女', age: '16岁', hobby: '看书', name: '赵柳1'},
{id: '7', class: '三年级1班', sex: '女', age: '16岁', hobby: '看书', name: '赵柳2'},
{id: '8', class: '三年级1班', sex: '女', age: '16岁', hobby: '旅游', name: '赵柳3'},
{id: '9', class: '三年级1班', sex: '女', age: '17岁', hobby: '动漫', name: '赵柳4'},
{id: '10', class: '三年级2班', sex: '男', age: '16岁', hobby: '羽毛球', name: '李四1'},
{id: '11', class: '三年级2班', sex: '男', age: '17岁', hobby: '羽毛球', name: '李四2'},
{id: '12', class: '三年级2班', sex: '女', age: '16岁', hobby: '看书', name: '王舞'},
{id: '13', class: '三年级2班', sex: '女', age: '16岁', hobby: '画画', name: '王舞2'}
]
this.buildMerge(this.dataList)
}
}
}
</script>
4.注意:
- 动态数据来源需要放开 init() 方法中调用接口的代码,且保证每条数据都有唯一的 id 值
- 在合并多个列时,需要在 buildMerge() 方法中定义对应的字段( firstObj、irstObjKey ),修改
for 方法中对应的字段名称 ( firstObjKey = dataList[i].对应合并列的字段名 ) - 本示例合并前四列,如你需要合并大于或小于当前列数,需要修改 objectSpanMethod() 方法中
对应的列号判断
5.本示例代码可以直接使用,且为原创,转载请带上链接谢谢!
打赏请扫码!!