注册
web

Vue+Element-UI 中 el-table 动态合并单元格 :span-method 方法

合并单元格


记录一下工作时遇到的 el-table 合并单元格的需求,超详细😊



el-table官方提供了合并单元格的方法与返回格式 如下:

在这里插入图片描述

根据叙述有了如下思路:

因为后端返回的数据非统一, 可能不是按照类别排好的😨, 所以官网的例子满足不了所有的需求所以我们通过遍历table的数据比较前后两个元素是否相等, 来构造一个spanArr用来存放rowspan, 最后通过rowspan的值来判断colspan的值😊.


案例如下, 这是我需要处理的一个表格:

需要根据数据动态的合并

在这里插入图片描述

对应的配置数组为

在这里插入图片描述


处理数据


因为获取的数据的非统一性, 我们首先要将数据根据我们想要合并的字段进行排序分组, 这里我实现了一个简单的方法来处理数据:


// data 为 表格数据 , params 为需要合并的字段
groupBy (data, params) {
const groups = {};
data.forEach(v => {
// 获取data中的传入的params属性对应的属性值
const group = JSON.stringify(v[params]);
// 把group作为groups的key,初始化value,循环时找到相同的v[params]时不变
groups[group] = groups[group] || [];
// 将对应找到的值作为value放入数组中
groups[group].push(v);
})
// 返回处理好的二维数组
return Object.values(groups);
},

此时打印一下我们的数据console.log(this.groupBy(this.tableListData.items, 'FirstIndex'))

在这里插入图片描述

如图, 我们已经将数据分好组并合并在一个数组中啦, FirstIndex相同的在一个数组


构造控制合并的数组spanArr


这里实现了一个方法, 用来构造一个spanArr数组赋予rowspan,即控制行合并



  • 接收重构数组 let arr = []
  • 设置索引 let pos = 0
  • 控制合并的数组 this.spanArr = []

先将groupby()处理好的数据再次用arr进行处理:连接所有数组成员为一个新数组

this.groupBy(this.tableListData.items, 'FirstIndex').map(v => (arr = arr.concat(v)))


现在处理好了数据,需要赋予原数据了:this.tableListData.items = arr


但是因为我是写在getSpanArr(data, params)方法中的,已经通过形参data将 this.tableListData.items传入了这里,如果想方便封装调用的话,不用每次使用都需要再次写入 this.tableListData.items = arr

于是想到一个办法,js数组的shift()和push()是直接修改数组所占内存的方法。

所以有:


arr.map(res => {
// 每次遍历都删除data && this.tableListData.items的第一个元素
data.shift()
// 每次遍历都将arr数组元素对应push进 data && this.tableListData.items
data.push(res)
})

还需要定义一个redata存放arr要合并字段的value

const redata = arr.map(v => v[params])


reduce处理spanArr数组 ⭐⭐


使用reduce方法比较redata前后两个元素是否相等,相等的话spanArr中对应索引的元素的值+1,并且在其后增加一个0占位(防止合并过后表格数据错位),否则的话增加一个1占位,并记录当前索引,往复循环,构造一个给 rowspan 取值判断合并的数组:


  const redata = arr.map(v => v[params])
redata.reduce((old, cur, i) => {
// old 上一个元素 cur 当前元素 i 索引
if (i === 0) {
// 第一次判断先增加一个 1 占位 ,索引为0
this.spanArr.push(1)
pos = 0
} else {
if (cur === old) {
this.spanArr[pos] += 1
this.spanArr.push(0)
} else {
this.spanArr.push(1)
pos = i
}
}
return cur
}, {})

看一下现在的数据spanArr, 这里传的参数为SecondIndex, 即表格的第二列

在这里插入图片描述

数组中大于0的数字就是我们数据中要合并的这组数据的数量, 同时也是这组数据需要合并的列数,而0就是代表这列不合并, 依次遍历,实现合并所选字段这一列的最终目的 如图理解:

在这里插入图片描述


返回最终结果


最后一步啦😊根据官方给的方法把我们处理好的spanArr传给rowspan即可


spanMethod({ row, column, rowIndex, columnIndex }) {
// 第一列
if (columnIndex === 0) {
const _row = this.spanArr[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col
}
}
}

效果如图!

在这里插入图片描述


完整代码


就很nice, !!最后把完整代码贴上:


// ......
mounted() {
this.getSpanArr(this.tableListData.items, 'FirstIndex');
},
methods: {
groupBy (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)
},
getSpanArr (data, params) {
let arr = []
let pos = 0
this.spanArr = []
this.groupBy(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.spanArr.push(1)
pos = 0
} else {
if (cur === old) {
this.spanArr[pos] += 1
this.spanArr.push(0)
} else {
this.spanArr.push(1)
pos = i
}
}
return cur
}, {})
},
spanMethod({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
const _row = this.spanArr[rowIndex];
const _col = _row > 0 ? 1 : 0;
return {
rowspan: _row,
colspan: _col
}
}
}
}

完美! 撒花!!!🎉🎉🎉


作者:小星星__
来源:juejin.cn/post/7238478149049483301

0 个评论

要回复文章请先登录注册