Element UI 的 table 单元格合并

article/2025/9/12 21:21:32

项目中遇到表格单元格合并的需求,在此记录整个解决过程。

项目使用的是 Element UI,表格使用的是 table 组件。Element UI 的 table 表格组件中对单元格进行合并,需要使用 table 组件的 span-method 属性。

先看一张成果图(完整代码放在末尾):

解决思路:

1、格式化后台返回的数据(根据实际数据格式处理)

项目后台返回的数据格式为树形结构,这里做简化展示:

[{'column1': '111','column2': '222','column3': '333','children1': [{'column6': 666,'column4': '4440','column5': '5550','children2': [{'column7': '77701','column8': '88801','column9': '99901'}]}]}
]

需要先将树结构数据转为一维数组:

// table 表格数据初始化处理,将树结构数据转为一维数组handleData(data, parentId) {data.map((res, index) => {var obj = {id: parentId}for (const key in res) {const isarr = Object.values(res).find((age) => {return Array.isArray(age)})if (isarr) {if (Array.isArray(res[key])) {for (let i = 0; i < res[key].length; i++) {Object.assign(obj, res[key][i])data.push(obj)res[key].splice(i, 1)if (res[key].length === 0) {data.splice(index, 1)}this.handleData(data, parentId)}} else {Object.assign(obj, { [key]: res[key] })}}}})return data}

因为后台返回的数据里没有唯一标识符,所以需要单独添加一个唯一标识表示转换为一维数组的数据是出自同一组树结构里。故此处在展开时单独加了一个 id 属性,用来代替唯一标识。如果后台返回的数据格式就是一个一维数组,可跳过数据格式化步骤。

2、在 data 中定义数据,需要合并几列就定义几个数组和索引

  data() {return {tableData: [],// 合并单元格column1Arr: [], // column1column1Index: 0, // column1索引column2Arr: [], // column2column2Index: 0, // column2索引column3Arr: [], // column3column3Index: 0, // column3索引column4Arr: [], // column4column4Index: 0, // column4column5Arr: [], // column5column5Index: 0, // column5索引column6Arr: [], // column6column6Index: 0 // column6索引}}

 3、定义合并函数

以第一行为基准,一层层对比,参数 data 就是格式化以后的表格数据,以每个数据里的唯一标识 id 作为合并的参照字段:

    // 初始化合并行数组mergeInit() {this.column1Arr = [] // column1this.column1Index = 0 // column1索引this.column2Arr = [] // column2this.column2Index = 0 // column2索引this.column3Arr = [] // column3this.column3Index = 0 // column3索引this.column4Arr = [] // column4this.column4Index = 0 // column4索引this.column5Arr = [] // column5this.column5Index = 0 // column5索引this.column6Arr = [] // column6this.column6Index = 0 // column6索引},// 合并表格mergeTable(data) {this.mergeInit()if (data.length > 0) {for (var i = 0; i < data.length; i++) {if (i === 0) {// 第一行必须存在,以第一行为基准this.column1Arr.push(1) // column1this.column1Index = 0this.column2Arr.push(1) // column2this.column2Index = 0this.column3Arr.push(1) // column3this.column3Index = 0this.column4Arr.push(1) // column4this.column4Index = 0this.column5Arr.push(1) // column5this.column5Index = 0this.column6Arr.push(1) // column6this.column6Index = 0} else {// 判断当前元素与上一元素是否相同// column1if (data[i].column1 === data[i - 1].column1 &&data[i].id === data[i - 1].id) {this.column1Arr[this.column1Index] += 1this.column1Arr.push(0)} else {this.column1Arr.push(1)this.column1Index = i}// column2if (data[i].column2 === data[i - 1].column2 &&data[i].id === data[i - 1].id) {this.column2Arr[this.column2Index] += 1this.column2Arr.push(0)} else {this.column2Arr.push(1)this.column2Index = i}// column3if (data[i].column3 === data[i - 1].column3 &&data[i].id === data[i - 1].id) {this.column3Arr[this.column3Index] += 1this.column3Arr.push(0)} else {this.column3Arr.push(1)this.column3Index = i}// column4if (data[i].column4 === data[i - 1].column4 &&data[i].id === data[i - 1].id) {this.column4Arr[this.column4Index] += 1this.column4Arr.push(0)} else {this.column4Arr.push(1)this.column4Index = i}// column5if (data[i].column5 === data[i - 1].column5 &&data[i].column4 === data[i - 1].column4 &&data[i].id === data[i - 1].id) {this.column5Arr[this.column5Index] += 1this.column5Arr.push(0)} else {this.column5Arr.push(1)this.column5Index = i}// column6if (data[i].column6 === data[i - 1].column6 &&data[i].column4 === data[i - 1].column4 &&data[i].id === data[i - 1].id) {this.column6Arr[this.column6Index] += 1this.column6Arr.push(0)} else {this.column6Arr.push(1)this.column6Index = i}}}}},

注意,同一组数据里可能会有多个  children1 或者 children2,这时合并的时候会有多个条件进行判断:

 

 4、table 组件属性 span-method 的单元格合并方法:

    handleSpanMethod({ row, column, rowIndex, columnIndex }) {if (columnIndex === 0 || columnIndex === 1) {// 第一列 column1const _row_1 = this.column1Arr[rowIndex]const _col_1 = _row_1 > 0 ? 1 : 0return {rowspan: _row_1,colspan: _col_1}} else if (columnIndex === 2) {// 第二列 column2const _row_2 = this.column2Arr[rowIndex]const _col_2 = _row_2 > 0 ? 1 : 0return {rowspan: _row_2,colspan: _col_2}} else if (columnIndex === 3) {// 第三列 column3const _row_2 = this.column3Arr[rowIndex]const _col_2 = _row_2 > 0 ? 1 : 0return {rowspan: _row_2,colspan: _col_2}} else if (columnIndex === 4) {// 第四列 column4const _row_2 = this.column4Arr[rowIndex]const _col_2 = _row_2 > 0 ? 1 : 0return {rowspan: _row_2,colspan: _col_2}} else if (columnIndex === 5) {// 第五列 column5const _row_2 = this.column5Arr[rowIndex]const _col_2 = _row_2 > 0 ? 1 : 0return {rowspan: _row_2,colspan: _col_2}} else if (columnIndex === 6) {// 第六列 column6const _row_2 = this.column6Arr[rowIndex]const _col_2 = _row_2 > 0 ? 1 : 0return {rowspan: _row_2,colspan: _col_2}}}

至此,整个单元格合并就完成了!

如果觉得写得还不错,还请点赞支持,感谢感谢感谢!!!

完整代码:

<template><div class="table-wrap"><el-table:data="tableData":span-method="handleSpanMethod":cell-style="{ background: '#FFFFFF' }"borderstyle="width: 100%"><el-table-column prop="id" label="序号" align="center" width="80"><template slot-scope="scope">{{ scope.row.id + 1 }}</template></el-table-column><el-table-column prop="column1" label="column1" align="center" /><el-table-column prop="column2" label="column2" align="center" /><el-table-column prop="column3" label="column3" align="center" /><el-table-column prop="column4" label="column4" align="center" /><el-table-column prop="column5" label="column5" align="center" /><el-table-column prop="column6" label="column6" align="center" /><el-table-column prop="column7" label="column7" align="center" /><el-table-column prop="column8" label="column8" align="center" /><el-table-column prop="column9" label="column9" align="center" /></el-table></div>
</template><script>
export default {name: 'CellMerge',data() {return {tableData: [],// 合并单元格column1Arr: [], // column1column1Index: 0, // column1索引column2Arr: [], // column2column2Index: 0, // column2索引column3Arr: [], // column3column3Index: 0, // column3索引column4Arr: [], // column4column4Index: 0, // column4column5Arr: [], // column5column5Index: 0, // column5索引column6Arr: [], // column6column6Index: 0 // column6索引}},mounted() {this.initTableData()},methods: {// 初始化表格数据initTableData() {const newTableData = [{'column1': '111','column2': '222','column3': '333','children1': [{'column6': 666,'column4': '4440','column5': '5550','children2': [{'column7': '77701','column8': '88801','column9': '99901'},{'column7': '77702','column8': '88802','column9': '99902'},{'column7': '77703','column8': '88803','column9': '99903'}]},{'column6': 666,'column4': '4441','column5': '5551','children2': [{'column7': '77711','column8': '88811','column9': '99911'}]},{'column6': 666,'column4': '4442','column5': '5552','children2': [{'column7': '77721','column8': '88821','column9': '99921'},{'column7': '77722','column8': '88822','column9': '99922'}]}]},{'column1': '111','column2': '222','column3': '333','children1': [{'column6': 666,'column4': '4440','column5': '5550','children2': [{'column7': '77701','column8': '88801','column9': '99901'}]},{'column6': 666,'column4': '4441','column5': '5551','children2': [{'column7': '77711','column8': '88811','column9': '99911'},{'column7': '77712','column8': '88812','column9': '99912'}]}]},{'column1': '111','column2': '222','column3': '333','children1': [{'column6': 666,'column4': '4440','column5': '5550','children2': [{'column7': '77701','column8': '88801','column9': '99901'},{'column7': '77702','column8': '88802','column9': '99902'},{'column7': '77703','column8': '88803','column9': '99903'}]},{'column6': 666,'column4': '4441','column5': '5551','children2': [{'column7': '77711','column8': '88811','column9': '99911'}]}]}]this.tableData = []newTableData.map((res, index) => {const parentId = indexthis.tableData.push.apply(this.tableData,this.handleData([res], parentId))})this.mergeTable(this.tableData)},// table 表格数据初始化处理,将树结构数据转为一维数组handleData(data, parentId) {data.map((res, index) => {var obj = {id: parentId}for (const key in res) {const isarr = Object.values(res).find((age) => {return Array.isArray(age)})if (isarr) {if (Array.isArray(res[key])) {for (let i = 0; i < res[key].length; i++) {Object.assign(obj, res[key][i])data.push(obj)res[key].splice(i, 1)if (res[key].length === 0) {data.splice(index, 1)}this.handleData(data, parentId)}} else {Object.assign(obj, { [key]: res[key] })}}}})return data},// 初始化合并行数组mergeInit() {this.column1Arr = [] // column1this.column1Index = 0 // column1索引this.column2Arr = [] // column2this.column2Index = 0 // column2索引this.column3Arr = [] // column3this.column3Index = 0 // column3索引this.column4Arr = [] // column4this.column4Index = 0 // column4索引this.column5Arr = [] // column5this.column5Index = 0 // column5索引this.column6Arr = [] // column6this.column6Index = 0 // column6索引},// 合并表格mergeTable(data) {this.mergeInit()if (data.length > 0) {for (var i = 0; i < data.length; i++) {if (i === 0) {// 第一行必须存在,以第一行为基准this.column1Arr.push(1) // column1this.column1Index = 0this.column2Arr.push(1) // column2this.column2Index = 0this.column3Arr.push(1) // column3this.column3Index = 0this.column4Arr.push(1) // column4this.column4Index = 0this.column5Arr.push(1) // column5this.column5Index = 0this.column6Arr.push(1) // column6this.column6Index = 0} else {// 判断当前元素与上一元素是否相同// column1if (data[i].column1 === data[i - 1].column1 &&data[i].id === data[i - 1].id) {this.column1Arr[this.column1Index] += 1this.column1Arr.push(0)} else {this.column1Arr.push(1)this.column1Index = i}// column2if (data[i].column2 === data[i - 1].column2 &&data[i].id === data[i - 1].id) {this.column2Arr[this.column2Index] += 1this.column2Arr.push(0)} else {this.column2Arr.push(1)this.column2Index = i}// column3if (data[i].column3 === data[i - 1].column3 &&data[i].id === data[i - 1].id) {this.column3Arr[this.column3Index] += 1this.column3Arr.push(0)} else {this.column3Arr.push(1)this.column3Index = i}// column4if (data[i].column4 === data[i - 1].column4 &&data[i].id === data[i - 1].id) {this.column4Arr[this.column4Index] += 1this.column4Arr.push(0)} else {this.column4Arr.push(1)this.column4Index = i}// column5if (data[i].column5 === data[i - 1].column5 &&data[i].column4 === data[i - 1].column4 &&data[i].id === data[i - 1].id) {this.column5Arr[this.column5Index] += 1this.column5Arr.push(0)} else {this.column5Arr.push(1)this.column5Index = i}// column6if (data[i].column6 === data[i - 1].column6 &&data[i].column4 === data[i - 1].column4 &&data[i].id === data[i - 1].id) {this.column6Arr[this.column6Index] += 1this.column6Arr.push(0)} else {this.column6Arr.push(1)this.column6Index = i}}}}},handleSpanMethod({ row, column, rowIndex, columnIndex }) {if (columnIndex === 0 || columnIndex === 1) {// 第一列 column1const _row_1 = this.column1Arr[rowIndex]const _col_1 = _row_1 > 0 ? 1 : 0return {rowspan: _row_1,colspan: _col_1}} else if (columnIndex === 2) {// 第二列 column2const _row_2 = this.column2Arr[rowIndex]const _col_2 = _row_2 > 0 ? 1 : 0return {rowspan: _row_2,colspan: _col_2}} else if (columnIndex === 3) {// 第三列 column3const _row_2 = this.column3Arr[rowIndex]const _col_2 = _row_2 > 0 ? 1 : 0return {rowspan: _row_2,colspan: _col_2}} else if (columnIndex === 4) {// 第四列 column4const _row_2 = this.column4Arr[rowIndex]const _col_2 = _row_2 > 0 ? 1 : 0return {rowspan: _row_2,colspan: _col_2}} else if (columnIndex === 5) {// 第五列 column5const _row_2 = this.column5Arr[rowIndex]const _col_2 = _row_2 > 0 ? 1 : 0return {rowspan: _row_2,colspan: _col_2}} else if (columnIndex === 6) {// 第六列 column6const _row_2 = this.column6Arr[rowIndex]const _col_2 = _row_2 > 0 ? 1 : 0return {rowspan: _row_2,colspan: _col_2}}}}
}
</script>
<style lang="scss" scoped>.table-wrap {width: 100%;height: 100%;padding: 20px;}
</style>

 


http://chatgpt.dhexx.cn/article/33RKaLqY.shtml

相关文章

vxe-table 合并单元格合并列

效果如下&#xff1a; 合并单元格&#xff08;表头&#xff09;&#xff1a; :edit-render"{autofocus: .vxe-input--inner}"是控制是否可编辑单元格&#xff0c;和:edit-config搭配使用 合并列方法绑定:span-method&#xff0c;具体如下 <vxe-tableref"xT…

element ui 的table单元格合并

element ui中的table表格数据是动态生成的&#xff0c;如果说后台要求我们对单元格进行合并&#xff0c;这个时候需要借助一个api,:span-method"arraySpanMethod",arraySpanMethod为我们自己编写的合并单元格的方法。 下图是我在项目中合并的单元格 数据都是从那后…

element table表格合并行和列

element-ui 官网案例&#xff1a; table合并行或列 通过给table传入span-method方法可以实现合并行或列&#xff0c;方法的参数是一个对象&#xff0c;里面包含当前行row、当前列column、当前行号rowIndex、当前列号columnIndex四个属性。该函数可以返回一个包含两个元素的数组…

Element_Table的单元格合并

在进行Table的单元格合并的时候&#xff0c;出现了bug&#xff1a;合并第一列的第 x 和 x1 行时&#xff0c;第x2行的数据被第二列的数据替换&#xff0c;之后表格中的数据均向前移动了一格&#xff0c;导致数据展示错乱 分析 在进行单元格合并时&#xff0c;未考虑到动态合并…

el-table 怎么合并相同单元格

问题背景 项目需求table表格中&#xff0c;相同的类型合并成一个单元格展示。 问题描述 el-table并没有相关的语法直接合并&#xff0c;需要我们自己传入一个方法返回一个数组格式&#xff0c;来确定要合并行列。 解决问题 首先需要在 el-table 标签上绑定:span-method&quo…

el-table合并单元格

根据id相同合并单元格 <el-table selection-change"handleSelectionChange" :span-method"objectSpanMethod" :data"tableData" ref"multipleTable" ><el-table-column :selectable"checkSelect" type"sel…

Ant table表格合并单元格使用

Ant 合并单元格覆盖样式 项目需求&#xff1a; 最后一列用来展示详情&#xff0c;表格左侧点击行切换&#xff1b;要求选中行的样式和详情信息用一个边框凸显出来 结果如下&#xff1a; 切换效果展示如下&#xff1a; 实现过程&#xff1a; 在ant合并单元格demo中&#xff…

table 表格合并行或列

合并单元格 <table><tbody><tr><th colspan"2">我是占位符</th><th colspan"2">我是占位符</th></tr><tr><th rowspan"2">我是占位符</th><th>我是占位符</th>&…

Element Table 单元格中嵌套表格(Table) 合并行效果

在Element中实现表格合并行功能一般是通过自定义span-method方法&#xff0c;此方法要求表格数据源中需要合并行的单元格中数据相同&#xff0c;根据相同数据来实现合并算法。 本例通过在父Table单元格中嵌套子Table实现合并行效果&#xff08;也使用了span-method方法&#x…

Html Table 合并单元格

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title></title> </head> <body> <ol><li>基本表格</li><table border"2" bordercolor"black" …

使用原生table合并单元格

先上个我要实现的页面 例子1&#xff1a; 就是最近要开发这么一个页面&#xff08;这是个原型图&#xff0c;没有美化&#xff0c;大概是这个样子也都懂&#xff09;&#xff0c;刚看到的时候说实话有点儿懵的&#xff0c;第一次见到这样的表格&#xff0c;可以看到里面有很多…

el-table 合并单元格(合并行)

1. 添加 :span-method"objectSpanMethod" 2. 写objectSpanMethod 方法 //#region 合并单元格// 这个方法是 element-ui提供的单元格合并方法// objectSpanMethod 传入了 { row, column, rowIndex, columnIndex }// row: 当前行// column: 当前列// rowIndex&…

table表格 ---合并单元格

1、合并表头 第一种方法 利用table的 :header-cell-style属性 <el-table:data"tableData"height"400px"max-height"400px"size"small":header-cell-style"headerStyle"fit > methods: {headerStyle({ row, rowIndex …

table表格单元格的合并详解

1.html实现表格 <el-tablemax-height"300":columns"columns":data"tableData":show-index"false":span-method"objectSpanMethod":header-cell-style"{ background: #eef0f6 }" /> 2.记录每个字段合并数的…

table表格--合并单元格

知识点概要&#xff1a; 1、colpan:横向合并"n"个单元格--n:默认1 2、rowspan:纵向合并"n"个单元格--n:默认1 代码demo&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/lo…

table表格中单元格的合并

目录 table表格中单元格的合并 table表格中单元格的合并很多朋友不一定了解&#xff0c;今天我就写一篇博客来跟大家分享一下table表格中的跨行合并和跨列合并。 我们先看一个合并过的表格&#xff0c;大家可以先思考一下这种表格通过代码是怎么实现的。 解析&#xff1a;我们…

类型“HTMLElement”上不存在属性“getContext”

ts警告&#xff1a;类型“HTMLElement”上不存在属性“getContext” 修改代码如下&#xff1a; const state reactive({canvasDom: null as HTMLCanvasElement | null,canvasCtx: null as CanvasRenderingContext2D | null, });onMounted(() > {state.canvasDom <HTML…

“TypeError: Cannot read properties of null (reading ‘getContext‘)“

目录 一、报错截图 二、使用场景 三、代码截图 四、报错原因 五、解决办法 一、报错截图 二、使用场景 第一次在vue项目种使用canvas&#xff0c;跟着网上教程做&#xff0c;标签canvas写好了&#xff0c;dom元素获取了&#xff0c;简单“画”了一下&#xff0c;运行之后报…

setcontext getcontext makecontext swapcontext

Linux上下文切换以及协程 上下文切换&#xff0c;听起来虚无缥缈&#xff0c;什么是上下文&#xff0c;切换又是指的是什么&#xff1f;其实上下文就可以理解为一个进程所运行的相关的寄存器值&#xff0c;即包括sp/bp/pc等值&#xff0c;换句话说&#xff0c;一个上下文&#…

android之getContext和getActivity介绍

image.png getContext View类中提供的方法&#xff0c;在继承了View的类中才可以调用。 返回的是当前View运行在哪个Activity Contex中&#xff0c;获取当前context的实例。 如果使用场景是Activity则相当于 this&#xff0c;如果使用场景是一个Server 那么获取的实例就是一个A…