2023.8.17今天我学习了如何使用el-table进行单元格的合并,效果如下:
在开发的过程中,如果有多个重复的值,我们希望可以进行合并显示,这样就不会显得重复太多,el-table有自带的方法:
Element - The world's most popular Vue UI framework
它这边给出的实例已经是每一个数组都有对应的字段和值
在给定的示例中,通过对 rowIndex
和 columnIndex
进行判断,实现对表格单元格的动态合并。具体的逻辑如下:
- 如果
rowIndex
是偶数(即偶数行),则进行以下判断:- 如果
columnIndex
是 0,则返回[1, 2]
,表示当前单元格需要横向合并 1 行,纵向合并 2 列。 - 如果
columnIndex
是 1,则返回[0, 0]
,表示当前单元格不需要进行合并。
- 如果
但是在开发过程中,我们遇到的数组可能是这样一对多关系的:
原始数据:
[
{
"id": 1,
"sub_name": "学科一",
"list": [
{
"id": 4,
"ward_name": "病区一"
},
{
"id": 5,
"ward_name": "病区二"
}
]
},
{
"id": 2,
"sub_name": "学科二",
"list": [
{
"id": 6,
"ward_name": "病区三"
},
{
"id": 7,
"ward_name": "病区四"
},
{
"id": 8,
"ward_name": "病区五"
}
]
},
{
"id": 3,
"sub_name": "学科一",
"list": [
{
"id": 9,
"ward_name": "病区六"
}
]
}
]
通过elementUI的实例我们发现,每个数组里面都要有对应的字段,所以我们要把外面的字段放在里面:
一、forEach循环赋值
let new_demo = []
demo.forEach(first_item => {//两层循环把外面的字段放在里面
first_item.list.forEach(second_item => {
second_item.sub_name = first_item.sub_name
})
new_demo.push(...first_item.list)
})
this.getFirstNameTableList(new_demo, 'sub_name')//合并方法,对应数据和参数名
console.log(new_demo)
效果:
这样就可以实现每一个数组都有对应的字段,然后就可以使用合并的方法。
二、合并方法(直接用,不需要改别的东西):
<template>
<div>
<el-table :span-method='objectSpanMethod'></el-table>
</div>
</template>
<script>
export default{
data(){
return{
spanFirstArr:[]
}
}
methods:{
// 合并第一个重复的行名称
getFirstNameTableList(data, params) {
let arr = []
let pos = 0
this.spanFirstArr = []
this.generalGeneralData(data, params).map(v => (arr = arr.concat(v)))
arr.map(res => {
data.shift()
data.push(res)
})
const redata = arr.map(v => v[params])
redata.reduce((old, cur, i) => {
if (i === 0) {
this.spanFirstArr.push(1)
pos = 0
} else {
if (cur === old) {
this.spanFirstArr[pos] += 1
this.spanFirstArr.push(0)
} else {
this.spanFirstArr.push(1)
pos = i
}
}
return cur
}, {})
},
// 重构新数据的方法
generalGeneralData(data, params) {
const groups = {}
data.forEach(v => {
const group = JSON.stringify(v[params])
groups[group] = groups[group] || []
groups[group].push(v)
})
return Object.values(groups)
},
objectSpanMethod({row, column, rowIndex, columnIndex}) {
if (columnIndex === 0) {//第一列
const _row = this.spanFirstArr[rowIndex]
const _col = _row > 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
}
}
},
}
}
</script>
三:完整代码:
<template>
<div>
<el-table :data='typeList' :span-method='objectSpanMethod'>
<el-table-column label='学科名称' prop='sub_name'/>
<el-table-column label='病区名称' prop='ward_name'/>
</el-table>
</div>
</template>
<script>
export default{
data(){
return{
spanFirstArr:[],
typeList:[]
}
},
created(){
this.getList()
},
methods:{
getList(){
let demo = [
{
"id": 1,
"sub_name": "学科一",
"list": [
{
"id": 4,
"ward_name": "病区一"
},
{
"id": 5,
"ward_name": "病区二"
}
]
},
{
"id": 2,
"sub_name": "学科二",
"list": [
{
"id": 6,
"ward_name": "病区三"
},
{
"id": 7,
"ward_name": "病区四"
},
{
"id": 8,
"ward_name": "病区五"
}
]
},
{
"id": 3,
"sub_name": "学科一",
"list": [
{
"id": 9,
"ward_name": "病区六"
}
]
}
]
let new_demo = []
demo.forEach(first_item => {//两层循环把外面的字段放在里面
first_item.list.forEach(second_item => {
second_item.sub_name = first_item.sub_name
})
new_demo.push(...first_item.list)
})
this.typeList = new_demo
this.getFirstNameTableList(this.typeList , 'sub_name')//合并方法,对应数据和参数名
},
// 合并第一个重复的行名称
getFirstNameTableList(data, params) {
let arr = []
let pos = 0
this.spanFirstArr = []
this.generalGeneralData(data, params).map(v => (arr = arr.concat(v)))
arr.map(res => {
data.shift()
data.push(res)
})
const redata = arr.map(v => v[params])
redata.reduce((old, cur, i) => {
if (i === 0) {
this.spanFirstArr.push(1)
pos = 0
} else {
if (cur === old) {
this.spanFirstArr[pos] += 1
this.spanFirstArr.push(0)
} else {
this.spanFirstArr.push(1)
pos = i
}
}
return cur
}, {})
},
// 重构新数据的方法
generalGeneralData(data, params) {
const groups = {}
data.forEach(v => {
const group = JSON.stringify(v[params])
groups[group] = groups[group] || []
groups[group].push(v)
})
return Object.values(groups)
},
objectSpanMethod({row, column, rowIndex, columnIndex}) {
if (columnIndex === 0) {//第一列
const _row = this.spanFirstArr[rowIndex]
const _col = _row > 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
}
}
},
}
}
</script>
扩展:
多个参数合并也可以通过同样的方式进行创建。
data(){
return{
spanSecondtArr:[]
}
}
methods:{
getList(){
xxxxxx上面的和之前一样
this.getFirstNameTableList(this.typeList , 'sub_name')//合并方法,对应数据和参数名
this.getSecondNameTableList(this.typeList , 'ward_name')//合并方法,对应数据和参数名
},
// 合并第二个重复的行名称(写法和第一个一样,换一个存放数据就好)
getSecondNameTableList(data, params) {
let arr = []
let pos = 0
this.spanSecondtArr = []//换一个存放数据参数
this.generalGeneralData(data, params).map(v => (arr = arr.concat(v)))//这个方法不变
arr.map(res => {
data.shift()
data.push(res)
})
const redata = arr.map(v => v[params])
redata.reduce((old, cur, i) => {
if (i === 0) {
this.spanSecondtArr .push(1)
pos = 0
} else {
if (cur === old) {
this.spanSecondtArr [pos] += 1
this.spanSecondtArr .push(0)
} else {
this.spanSecondtArr .push(1)
pos = i
}
}
return cur
}, {})
},
objectSpanMethod({row, column, rowIndex, columnIndex}) {
if (columnIndex === 0) {//第一列
const _row = this.spanFirstArr[rowIndex]
const _col = _row > 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
}
}
if (columnIndex === 1) {//第二列
const _row = this.spanSecondArr[rowIndex]
const _col = _row > 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
}
}
},
}
效果如下: