el-table单元格合并
通过给 table 传入span-method
方法可以实现合并行或列, 方法的参数是一个对象,里面包含当前行 row
、当前列 column
、当前行号 rowIndex
、当前列号 columnIndex
四个属性。 该函数可以返回一个包含两个元素的数组,第一个元素代表 rowspan
,第二个元素代表 colspan
。 也可以返回一个键名为 rowspan
和 colspan
的对象。
效果展示
实现方法
1. 函数参数:
tableData
:指向包含表格数据的数组。mergeArr
:指向一个包含要合并的表格字段名的数组。orderId
:表示用于处理鼠标悬停高亮的分组名
2. 定义响应式变量
mergeObj
:将存储有关每个列需要跨越多少单元格的信息。currentIndex
:用于存储当前鼠标悬停的索引,以进行鼠标交互。
js
const mergeObj = ref({});
const currentIndex = ref('');
3. 实现合并行或列
此函数用于确定单元格应跨越多少行和列(合并)。它检查列的属性(字段名)是否在 mergeArr
中。如果是,则查看 mergeObj
来确定跨越的值。如果值大于 0,则表示单元格应该垂直跨越,如果值为 0,则表示由于合并应隐藏单元格。
js
/**
* span-method属性对应方法 实现合并行或列
* @param {*} param0
* @returns
*/
const objectSpanMethod = ({ column, rowIndex }) => {
if(mergeArr.value.indexOf(column.property) !== -1) {
// 判断其值是不是为0
if(mergeObj.value[column.property][rowIndex]) {
return [mergeObj.value[column.property][rowIndex], 1]
} else {
// 如果为0则为需要合并的行
return [0, 0];
}
}
}
4. 行类名添加
解决高亮问题
js
/**
* row-class-name属性对应方法
* @param {*} row
* @returns
*/
const tableRowClassName = (row) => {
if (row.row[orderId.value] == currentIndex.value) {
return 'hover-bg'
} else {
return ''
}
};
5. 单元格鼠标交互处理函数:
js
/**
* cell-mouse-enter属性对应方法
* @param {*} row
*/
const handleCellMouseEnter = (row) => {
currentIndex.value = row[orderId.value];
};
/**
* cell-mouse-leave属性对应方法
*/
const handleCellMouseLeave = () => {
currentIndex.value = ''
};
完整代码
js
import { ref,watch } from "vue";
/**
* 合并相同的多列单元格
* @param {ref([])} tableData table数据
* @param {ref({})} mergeArr table字段名
* @param {ref('')} orderId 组名 可取table中数据相同的字段名,用于解决鼠标浮动高亮问题
* @returns
*/
export default function spanMethod(tableData,mergeArr,orderId) {
const mergeObj = ref({});
const currentIndex = ref('');
watch([tableData,mergeArr],()=>{
mergeArr.value.forEach((key) => {
let count = 0; // 用来记录需要合并行的起始位置
mergeObj.value[key] = []; // 记录每一列的合并信息
tableData.value.forEach((item, index) => {
// index == 0表示数据为第一行,直接 push 一个 1
if(index === 0) {
mergeObj.value[key].push(1);
} else {
// 判断当前行是否与上一行其值相等 如果相等 在 count 记录的位置其值 +1 表示当前行需要合并 并push 一个 0 作为占位
if(item[key] && item[key] === tableData.value[index - 1][key]) {
mergeObj.value[key][count] += 1;
mergeObj.value[key].push(0);
} else {
// 如果当前行和上一行其值不相等
count = index; // 记录当前位置
mergeObj.value[key].push(1); // 重新push 一个 1
}
}
})
})
},{
deep: true,
immediate: true
})
/**
* cell-mouse-enter属性对应方法
* @param {*} row
*/
const handleCellMouseEnter = (row) => {
currentIndex.value = row[orderId.value];
};
/**
* cell-mouse-leave属性对应方法
*/
const handleCellMouseLeave = () => {
currentIndex.value = ''
};
/**
* row-class-name属性对应方法
* @param {*} row
* @returns
*/
const tableRowClassName = (row) => {
if (row.row[orderId.value] == currentIndex.value) {
return 'hover-bg'
} else {
return ''
}
};
/**
* span-method属性对应方法 实现合并行或列
* @param {*} param0
* @returns
*/
const objectSpanMethod = ({ column, rowIndex }) => {
if(mergeArr.value.indexOf(column.property) !== -1) {
// 判断其值是不是为0
if(mergeObj.value[column.property][rowIndex]) {
return [mergeObj.value[column.property][rowIndex], 1]
} else {
// 如果为0则为需要合并的行
return [0, 0];
}
}
}
return {
objectSpanMethod,
handleCellMouseEnter,
handleCellMouseLeave,
tableRowClassName
};
}
使用
html
<template>
<el-table
:data="tableData"
:span-method="objectSpanMethod"
border
@cell-mouse-enter="handleCellMouseEnter"
@cell-mouse-leave="handleCellMouseLeave"
:row-class-name="tableRowClassName">
<el-table-column label="详评阅标项" prop="subitemTitle" width="200" />
<el-table-column label="详评阅标内容" prop="subitemContent" width="200" />
<el-table-column label="专家阅标" prop="optionValue" width="200" />
<el-table-column label="供应商应答情况" prop="answerData" width="200" />
<el-table-column label="详评阅标项所在投标文件位置" prop="bidBookPage" width="200" />
</el-table>
</template>
<script setup>
import spanMethod from "@/hooks/spanMethod";
const mergeArr = ref(['id','subitemTitle','subitemContent','optionValue','answerData']);
const orderId = ref('id');
const tableData = ref([
{
"id": "abc995d7918c4f4a9af7cabdb45e1b07",
"expertBiddingId": null,
"biddingSubitemId": "bs04",
"templateSubitemId": "772759e0-7a74-42e1-b918-fc3c17d6f5ea",
"subitemTitle": "商务文件编制质量",
"subitemContent": "商务文件编制(按提交资料的完整性进行评定):优秀得8-10分,较好的得5-7分,一般的得0-4分",
"answerOptions": "优秀(8-10分);较好(5-7分);一般(0-4分)",
"answerOptionsRule": "优秀:最大值10:最小值8:默认值9;较好:最大值7:最小值:5:默认值6;一般:最大值4:最小值0:默认值2",
"optionValue": null,
"optionDesc": null,
"scoreResult": null,
"autoScore": null,
"createUserId": null,
"updateUserId": null,
"delFlag": null,
"pos": 2,
"expertBiddingIds": null
},
...
])
const {
objectSpanMethod,
handleCellMouseEnter,
handleCellMouseLeave,
tableRowClassName,
} = spanMethod(tableData,mergeArr,orderId);
</script>
<style scoped lang="scss">
:deep(.el-table__body .el-table__row.hover-bg td) {
background-color: #F5F7FA;
}
</style>