element ui 构建复杂表格,动态合并行列及多级表头
Elementui中Tale实现根据id相同动态合并单元格 vue3版本
<template> <div class="merge-table-container"> <el-table :data="tableData" border style="width: 100%" :span-method="objectSpanMethod" > <el-table-column prop="id" label="ID" width="80"></el-table-column> <el-table-column prop="name" label="项目名称"></el-table-column> <el-table-column prop="value" label="数值"></el-table-column> </el-table> </div> </template> <script setup> import { ref, onMounted } from 'vue' const tableData = ref([]) const spanArr = ref([]) // 存储合并规则 // 生成测试数据 const generateData = () => { const mockData = [ { id: 1, name: '项目A', value: 100 }, { id: 1, name: '项目A', value: 200 }, { id: 1, name: '项目A', value: 300 }, { id: 2, name: '项目B', value: 400 }, { id: 2, name: '项目B', value: 500 }, { id: 3, name: '项目C', value: 600 }, { id: 3, name: '项目C', value: 700 }, { id: 3, name: '项目C', value: 800 }, { id: 3, name: '项目C', value: 900 } ] tableData.value = mockData calculateSpans(mockData) } // 计算合并规则 const calculateSpans = (data) => { const tempSpanArr = [] let pos = 0 data.forEach((item, index) => { if (index === 0) { tempSpanArr.push(1) pos = 0 } else { if (data[index].id === data[index - 1].id) { tempSpanArr[pos] += 1 tempSpanArr.push(0) } else { tempSpanArr.push(1) pos = index } } }) spanArr.value = tempSpanArr } // 合并单元格方法 const objectSpanMethod = ({ row, column, rowIndex, columnIndex }) => { if (columnIndex === 0 ) {//|| columnIndex === 1 const rowspan = spanArr.value[rowIndex] const colspan = rowspan > 0 ? 1 : 0 return { rowspan: rowspan, colspan: colspan } } } onMounted(() => { generateData() }) </script> <style scoped> .merge-table-container { padding: 20px; } </style>
另一种
<template> <div> <el-table :data="tableData" :span-method="objectSpanMethod" border style="width: 70%; margin-top: 20px"> <el-table-column prop="id" label="ID"> </el-table-column> <el-table-column prop="name" label="姓名"> </el-table-column> <el-table-column prop="home" label="家庭住址"> </el-table-column> <el-table-column prop="phone" label="电话"> </el-table-column> <el-table-column prop="amount1" label="数值 1(元)"> </el-table-column> <el-table-column prop="amount2" label="数值 2(元)"> </el-table-column> <el-table-column prop="amount3" label="数值 3(元)"> </el-table-column> </el-table> </div> </template> <script> export default { data() { return { tableData: [{ id: '1', name: '王小虎', home: '上海', phone: '123456', amount1: '234', amount2: '3.2', amount3: 10 }, { id: '1', name: '王小虎', home: '上海', phone: '123456', amount1: '165', amount2: '4.43', amount3: 12 }, { id: '1', name: '王小虎', home: '上海', phone: '123456', amount1: '324', amount2: '1.9', amount3: 9 }, { id: '2', name: '小张', home: '北京', phone: '456789', amount1: '621', amount2: '2.2', amount3: 17 }, { id: '3', name: '小刘', home: '南京', phone: '789456', amount1: '539', amount2: '4.1', amount3: 15 }] }; }, methods: { objectSpanMethod({ row, column, rowIndex, columnIndex }) { if(columnIndex === 0){ //此处处理第一列 const _row = (this.flitterData(this.tableData).one)[rowIndex] const _col = _row > 0 ? 1 : 0 return { rowspan: _row, colspan: _col } }else if(columnIndex === 1 || columnIndex === 2 || columnIndex === 3){ //此处处理第二、三、四列 const _row = (this.flitterData2(this.tableData).one)[rowIndex] const _col = _row > 0 ? 1 : 0 return { rowspan: _row, colspan: _col } } }, flitterData(arr) { let spanOneArr = []; // 初始化一个空数组,用于存储合并行的标记 let concatOne = 0; // 初始化变量,用于记录上一个需要合并的元素的索引 arr.forEach((item, index)=>{ // 遍历数组 if(index === 0){ spanOneArr.push(1) // 如果是第一个元素,直接标记为1(表示这是一个新的开始) }else{ if(item.id === arr[index-1].id){ // 如果当前元素的id与上一个元素的id相同 spanOneArr[concatOne] += 1 // 则将上一个标记加1(表示需要合并的行数增加) spanOneArr.push(0) // 然后标记当前位置为0(表示这不是一个新的开始) }else{ spanOneArr.push(1) // 如果id不同,则标记当前位置为1(表示这是一个新的开始) concatOne = index // 更新记录上一个需要合并的元素的索引 }; } }); return { one: spanOneArr // 返回标记数组 } }, flitterData2(arr) { let spanOneArr = []; // 初始化空数组 let concatOne = 0; // 初始化变量 arr.forEach((item, index)=>{ // 遍历数组 if(index === 0){ spanOneArr.push(1) // 第一个元素标记为1 }else{ if(item.id === arr[index-1].id && item.name === arr[index-1].name){ // 判断id和name是否都相同 spanOneArr[concatOne] += 1 // 如果相同,则更新上一个标记 spanOneArr.push(0) // 标记当前位置为0 }else{ spanOneArr.push(1) // 如果不同,标记当前位置为1 concatOne = index // 更新索引 }; } }); return { one: spanOneArr // 返回标记数组 } } } }; </script>
如图

参考https://blog.csdn.net/neverr_/article/details/145699744
<!-- 表格 --> <el-table :data="tableData" style="width: 80%; margin: 20px" :header-cell-style="{background: '#F8F8F8', height: '40px', padding: '0', color: '#333333'}" border :span-method="objectSpanMethod" > <el-table-column align="center" header-align="center" :show-overflow-tooltip="true" width="100" > <template slot-scope="scope"> {{ scope.row.index + 1 }} </template> </el-table-column> <el-table-column prop="subjects" label="费用科目" align="center" header-align="center" :show-overflow-tooltip="true"></el-table-column> <el-table-column prop="classType" label="分类" align="center" header-align="center" :show-overflow-tooltip="true" ></el-table-column> <el-table-column prop="price" label="金额" align="center" header-align="center" :show-overflow-tooltip="true" ></el-table-column> </el-table>
return{
tableData:[{
index:0,
subjects:'一次性就废',
price:'1,200.00元'
},{
index:1,
subjects:'医疗备用金',
price:'1,200.00元'
},{
index:2,
subjects:'试住费',
price:'1,200.00元'
},{
index:3,
subjects:'餐费',
classType: '餐费(长者+保姆)',
price:'1,200.00元'
},{
index:4,
subjects:'餐费',
classType: '餐费(长者)',
price:'1,200.00元'
}]
}
//合并第一列
flitterData (arr) {
let spanOneArr = []
let concatOne = 0
arr.forEach((item, index) => {
console.log(item,index)
if (index === 0) {
spanOneArr.push(1)
} else {
if (item.subjects === arr[index - 1].subjects) { //第一列需合并相同内容的判断条件
spanOneArr[concatOne] += 1
spanOneArr.push(0)
} else {
spanOneArr.push(1)
concatOne = index
};
}
});
return {
one: spanOneArr,
}
},
objectSpanMethod ({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 1) { // 判断哪一列
const _row = (this.flitterData(this.tableData).one)[rowIndex]
const _col = _row > 0 ? 1 : 0
return {
rowspan: _row,
colspan: _col
};
}
},
如图

参考https://blog.csdn.net/weixin_51565477/article/details/119749150

参考https://zhuanlan.zhihu.com/p/717324878

浙公网安备 33010602011771号