表格部分合并(element ui)
效果如图所示,只合并中间四列的数据
基础内容
进行相关功能之前你可能需要先知道表格合并需要的知识
这是一个最基本的html表格 要想实现行合并就需要在合并的 td 标签处增加 colspan 属性 来控制向右合并的数量,告诉table需要向右合并几个
<table border="1">
<tr>
<td colspan="2">标题</td>
</tr>
<tr>
<td>内容1</td>
<td>内容2</td>
</tr>
</table>
Element中使用
但是在element中,由于是封装过的组件所以并没有提供在组件上直接写入colspan的属性,但是提供了 span-method 函数用于获取合并的逻辑,每渲染一个单元格就会调用一次该函数
1. span-method参数解释以及使用
他是一个回调函数 给了一个对象 里面包含了四个信息
<template>
<el-table :span-method="spanMethod">
<!-- 此处省略内容部分 -->
</el-table>
</template>
<script setup lang="ts">
/**
*
* @param scope.columnIndex 当前列下标
* @param scope.rowIndex 当前行下标
* @param scope.column 当前列数据
* @param scope.row 当前行数据
*/
function spanMethod(scope: any) {
console.log(scope)
// 把四个参数解构出来
let { columnIndex, rowIndex, column, row } = scope
// 查看调用顺序
console.log(columnIndex, rowIndex)
}
</script>
列行输出顺序
2.实现合并第二行第一二列的单元格
函数调用时需要返回的合并信息
{
rowspan: 1, //向下合并的列的数量 1代表不合并
colspan: 2 //我门需要关注的时合并行的 现在为2的意思就是从当前个开始向后合并一个加起来就是2
}
<script setup lang="ts">
function spanMethod(scope: any) {
let { columnIndex, rowIndex } = scope
// 找到要合并的开始位置
if (columnIndex == 0 && rowIndex == 0) {
return {
rowspan: 1,
colspan: 2
}
}
// 由于上面合并了这一个 所以这里的 colspan 为0 (只要时被合并的单元格都为0)
if (columnIndex == 1 && rowIndex == 0) {
return {
rowspan: 1,
colspan: 0
}
}
}
</script>
下图是合并的结果
基本能看出调用顺序是这么来的
3.动态思路
根据上面的合并的思路我们知道只需要计算好columnIndex 和 rowIndex出现的位置就能合并成功,我们可以 弄一个和表格差不多的结构和这两个位置数据一一对应到时候直接返回就行
首先就是合并几个那起始位置的数就是几,被合并的数就是0, 没有被合并的就是1,展示了几个数据数组中就有几个长度的数
比如 上方合并的数据就应该是 [2,0,1,1]
那如果我生成了每行是合并数据那不就简单了
{
1:[2,0,1,1],
2: [2,0,1,1]
}
4.完整代码 vue3 + ts
<template>
<el-table :data="tableData" :span-method="spanMethod">
<!-- 此处省略内容部分 -->
</el-table>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// 表格数据
const tableData = ref([
{
gasName: '两氧化碳',
unit: '%',
L1: '1',
L2: '1',
L3: '2',
L4: '3'
},
{
gasName: '一氧化两氢',
unit: '%',
L1: '1',
L2: '2',
L3: '2',
L4: '2'
},
{
gasName: '四氢化碳',
unit: '%',
L1: '5',
L2: '5',
L3: '5',
L4: '5'
}
])
/**
*
* @param data 表格数据
* @param rowIndex 要第几行的数据
*/
function getSpanNumber(data: { [key: string]: any }[], rowIndex: number) {
let length = Array.isArray(data) ? data.length : 0
if (length > 0) {
// 声明一个装合并的对象
let _rrL: { [key: string]: number[] } = {}
for (let i = 0; i < length; i++) {
// 需要这四个字段进行合并 并且这四个字段是依次排列的
let _rl = ['L1', 'L2', 'L3', 'L4']
// 变化的下标
let _ri = 0
// 对比的数据
let _rt = ''
// 相同数据出现了几次 默认为1
let _rp = 1
// 把需要的合并的列信息依次装起来
let _rr = [1]
// 计算横坐标
_rl.map((item, index) => {
if (index == 0) _rt = data[i][_rl[0]]
if (data[i][item] && data[i][item] == _rt) {
_rr[index] = 0
_rr[_ri] = _rp
_rp += 1
} else {
_rt = data[i][_rl[index]]
_rp = 2
_rr[index] = 1
_ri = index
}
})
// 因为我们只用合并其中的四个字段,所以要把其他列的数据补上
_rrL[i] = [1, 1, ..._rr, 1, 1]
}
//返回相对应行的合并数据
return _rrL[rowIndex]
} else {
return [1]
}
}
function spanMethod(scope: any) {
let { columnIndex, rowIndex } = scope
let nameSpan = getSpanNumber(tableData.value, rowIndex)
// 因为只需要合并四个字段 所以需要将前后两列进行排除
if ([0, 1, 6, 7].indexOf(columnIndex)! - 1) {
return {
rowspan: 1,
colspan: nameSpan[columnIndex]
}
}
}
</script>