vue中table表头单元格合并(附单行、多级表头代码)
问题描述
本文记录el-table
表头合并的多种情况,并提出对应解决方案,估计能帮到部分道友
原生table知识点复习
- 我们知道:一个简单的
table
表格一般由一个或多个tr
、th
或td
标签组成(嵌套) tr
标签定义表格行(table-row
即为tr
)th
标签定义表头(table-header
即为th
)td
标签定义表格单元格
再复杂的表格还包括
caption
、col
、colgroup
、thead
、tfoot
、tbody
等标签,这里暂不延伸
而合并单元格主要使用的是colspan
和rouspan
属性,即为可设置横跨列
和横跨行
的值
而合并单元格主要使用的是colspan
和rouspan
属性,即为可设置横跨列
和横跨行
的值
而合并单元格主要使用的是colspan
和rouspan
属性,即为可设置横跨列
和横跨行
的值
知道这两个属性以后,我们结合一个具体demo来看,就很好的理解了
原生表格demo
假设我们需要做一个周一到周末的表格,记录一下工作内容,如下效果图:
对应代码是这样的:
<table border="1"> <tr> <th>工作日</th> <th>工作日</th> <th>工作日</th> <th>工作日</th> <th>工作日</th> <th>周末</th> <th>周末</th> </tr> <tr> <th>周一</th> <th>周二</th> <th>周三</th> <th>周四</th> <th>周五</th> <th>周六</th> <th>周日</th> </tr> <tr> <td>上班</td> <td>上班</td> <td>上班</td> <td>上班</td> <td>上班</td> <td>加班</td> <td>加班</td> </tr> </table>
但是,我们想把五个工作日和两个周末进行合并一下,这样看起来更加优雅一些,如下需求
由图示,我们知道第一行的工作日一共有5个,我们先
把后4个工作日隐去使其消失,再
让第一个工作日横跨5个单元格宽度,即横跨5列(原本默认都是横跨1列)
先隐去后四个工作日单元格
<tr> <th>工作日</th> <th style="display: none;">工作日</th> <th style="display: none;">工作日</th> <th style="display: none;">工作日</th> <th style="display: none;">工作日</th> <th>周末</th> <th>周末</th> </tr>
变成这样的效果了
- 这样的话,我们只需要,再让第一个工作日单元格宽度变宽一些,占据五个单元格,这样的话,宽度有了,就把两个周末挤回到原来正常的位置了
- 那,如何让第一个工作日单元格,占据五个单元格的宽度呢?
- 或者说,如何让一个单元格横跨5列?
- 很简单:
<th colspan="5">工作日</th>
即可 rowspan
同理,不赘述
需求完成效果图:
对应需求完成代码:
<table border="1"> <tr> <th colspan="5">工作日</th> <th style="display: none;">工作日</th> <th style="display: none;">工作日</th> <th style="display: none;">工作日</th> <th style="display: none;">工作日</th> <th colspan="2">周末</th> <th style="display: none;">周末</th> </tr> <tr> <th>周一</th> <th>周二</th> <th>周三</th> <th>周四</th> <th>周五</th> <th>周六</th> <th>周日</th> </tr> <tr> <td>上班</td> <td>上班</td> <td>上班</td> <td>上班</td> <td>上班</td> <td>加班</td> <td>加班</td> </tr> </table>
所以,通过上面的demo,我们可以得出一个结论:
合并单元格规律结论
合并单元格需要 先隐藏相关单元格,再让某个单元格横向或竖向延伸宽度或高度合并单元格需要 先隐藏相关单元格,再让某个单元格横跨列,或竖跨行
最后我们审查一下dom
元素,发现还真是这样的
el-table单层表头合并案例
无论是饿了么UI还是Iview等相关的UI组件库,都是给原生table套壳子封装
的,所以若是需要合并相应单元格,我们依旧可以使用上述的思想方式
我们继续通过案例来看一下,在UI组件库中如何操作合并单元格
本文以表头单元格合并举例,若是有表体单元格合并的需求,可以看之前的这篇文章:https://www.jb51.net/article/281738.htm
案例一
效果图:
代码:
header-cell-style
函数用于给表头添加样式,其返回的值会被添加到表头对应样式中去
注意函数的形参中的column.id
为单元格的class
类
大家最好打印一下,结合审查dom
看类名
<template> <el-table :data="tableData" border style="width: 600" :header-cell-style="headerCellStyle" > <el-table-column prop="name" label="姓名、年龄、家乡" width="150" align="center" ></el-table-column> <el-table-column prop="age" label="年龄" width="150" align="center" ></el-table-column> <el-table-column prop="home" label="家乡" width="150" align="center" ></el-table-column> <el-table-column prop="hobby" label="爱好" width="150" align="center" ></el-table-column> </el-table> </template> <script> export default { data() { return { tableData: [ { name: "孙悟空", age: 500, home: "花果山水帘洞", hobby: "大闹天宫", }, { name: "猪八戒", age: 88, home: "高老庄", hobby: "吃包子", }, { name: "沙和尚", age: 1000, home: "通天河", hobby: "游泳", }, { name: "唐僧", age: 99999, home: "东土大唐", hobby: "取西经", }, ], }; }, methods: { headerCellStyle({ row, column, rowIndex, columnIndex }) { // 第一步:设置表头的第0列暂不操作,将地1列和第2列隐去使其消失 if ((columnIndex == 1) | (columnIndex == 2)) { return { display: "none" }; } // 第二步, 由于1、2列没有了,后续列就会贴上来(后续列往左错位问题) if ((rowIndex == 0) & (columnIndex == 0)) { // 解决后续列错位问题,就是将隐去的第1、2列的位置再补上,通过第0列来补 this.$nextTick(() => { // 原来第0列只占据一个位置,现在要去占据三个位置。即占据三列,即设置为横向三个单元格 document.querySelector(`.${column.id}`).setAttribute("colspan", "3"); // 这里的column.id实际是dom元素的class,故用点.不用井#,可审查dom验证 // 通过设置原生的colspan属性,让原来的第一列只占据一个单元格的表头占据3个单元格即可 }); } }, }, }; </script> <style lang="less"> .el-table { th { font-weight: bold; color: #333; } } </style>
看,基本上一样的用法:先隐藏再设置横跨竖跨单元格
colspan='number' 属性,设置单元格可以横跨几列(默认一个单元格横向只占据一列)
案例二
效果图:
代码:
headerCellStyle({ row, column, rowIndex, columnIndex }) { // 第一步:隐去第2列单元格 if (columnIndex == 2) { return { display: "none" }; } // 第二步,让第1列单元格横跨两列(默认单元格只是横跨一列) if ((rowIndex == 0) & (columnIndex == 1)) { this.$nextTick(() => { document.querySelector(`.${column.id}`).setAttribute("colspan", "2"); }); } },
案例三
效果图:
代码:
headerCellStyle({ row, column, rowIndex, columnIndex }) { // 第一步:隐去第3列单元格 if (columnIndex == 3) { return { display: "none" }; } // 第二步,让第2列单元格横跨两列(默认单元格只是横跨一列) if ((rowIndex == 0) & (columnIndex == 2)) { this.$nextTick(() => { document.querySelector(`.${column.id}`).setAttribute("colspan", "2"); }); } },
案例四
效果图:
代码:
headerCellStyle({ row, column, rowIndex, columnIndex }) { // 第一步:隐去第1、2、3列单元格 let hideColArr = [1, 2, 3]; if (hideColArr.includes(columnIndex)) { return { display: "none" }; } // 第二步,让第0列单元格横跨四列(默认单元格只是横跨一列) if ((rowIndex == 0) & (columnIndex == 0)) { this.$nextTick(() => { document.querySelector(`.${column.id}`).setAttribute("colspan", "4"); }); } },
el-table多级表头合并案例
- 多级表头,需要进一步通过
rowIndex
去找到对应的单元格 - 因为单层表头,表头只有1行,
rowIndex
肯定是0,所以写不写都无所谓 - 但是多级表头有不少行,所以需要使用
columnIndex,rowIndex
进一步定位单元格 - 类似于通过
X轴 Y轴
的坐标定位到某个单元格位置
案例五
效果图:
代码:
html部门需要el-table-column标签进行嵌套
<template> <el-table :data="tableData" border style="width: 600" :header-cell-style="headerCellStyle" > <el-table-column prop="name" label="姓名" width="150" align="center"> <el-table-column prop="name" label="三列基础信息" width="150" align="center" ></el-table-column> </el-table-column> <el-table-column prop="name" label="年龄" width="150" align="center"> <el-table-column prop="age" label="年龄" width="150" align="center" ></el-table-column> </el-table-column> <el-table-column prop="name" label="家乡" width="150" align="center"> <el-table-column prop="home" label="家乡" width="150" align="center" ></el-table-column> </el-table-column> <el-table-column prop="hobby" label="爱好" width="150" align="center" ></el-table-column> </el-table> </template>
js部分继续先隐藏再延伸相关单元格
headerCellStyle({ row, column, rowIndex, columnIndex }) { // 把第1列第1行和第2列第1行的单元格隐去 if ((columnIndex == 1) | (columnIndex == 2)) { if (rowIndex == 1) { // 加上rowIndex精准定位 return { display: "none" }; } } // 然后让第0列第1行的单元格横向占据3个单元格位置填充刚刚隐去导致的空白 if ((columnIndex == 0) & (rowIndex == 1)) { // 加上rowIndex精准定位 this.$nextTick(() => { document.querySelector(`.${column.id}`).setAttribute("colspan", "3"); }); } },
案例六
效果图:
代码:
依旧是嵌套
<template> <el-table :data="tableData" border style="width: 600" :header-cell-style="headerCellStyle" > <el-table-column prop="name" label="基本信息(姓名、年龄、家乡)" align="center" > </el-table-column> <el-table-column prop="age" label="年龄" align="center" > </el-table-column> <el-table-column prop="home" label="家乡" align="center" > </el-table-column> <el-table-column prop="kind" label="所属种族" align="center"> </el-table-column> <el-table-column label="重要信息" align="center"> <el-table-column label="公开重要信息" align="center"> <el-table-column prop="nickname" label="法号" align="center"> </el-table-column> <el-table-column prop="hobby" label="爱好&性格" align="center"> </el-table-column> <el-table-column prop="personality" label="性格" align="center"> </el-table-column> </el-table-column> <el-table-column label="保密重要信息" align="center"> <el-table-column prop="bornBackground" label="出身背景" align="center"> </el-table-column> <el-table-column prop="skill" label="技能" align="center"> </el-table-column> </el-table-column> </el-table-column> </el-table> </template> <style lang="less"> .el-table { th { font-weight: bold; color: #333; } } </style>
先找到dom,再操作dom
<script> export default { data() { return { tableData: [ { name: "孙悟空", age: 500, home: "花果山水帘洞", kind: "monkey", nickname: "斗战胜佛", hobby: "大闹天宫", personality: "勇敢坚韧、疾恶如仇", bornBackground: "仙石孕育而生", skill: "72变、筋斗云", }, { name: "猪八戒", age: 88, home: "高老庄", kind: "pig", nickname: "净坛使者", hobby: "吃包子", personality: "好吃懒做、贪图女色", bornBackground: "天蓬元帅错投猪胎", skill: "36变", }, { name: "沙和尚", age: 1000, home: "通天河", kind: "human", nickname: "金身罗汉", hobby: "游泳", personality: "憨厚老实、任劳任怨", bornBackground: "卷帘大将被贬下界", skill: "18变", }, { name: "唐僧", age: 99999, home: "东土大唐", kind: "human", nickname: "檀功德佛", hobby: "取西经", personality: "谦恭儒雅、愚善固执", bornBackground: "金蝉子转世", skill: "念紧箍咒", }, ], }; }, methods: { headerCellStyle({ row, column, rowIndex, columnIndex }) { /** * 合并:基本信息(姓名、年龄、家乡)单元格【通过行与列的索引来合并】 * */ let colArr = [1, 2]; if (colArr.includes(columnIndex)) { if (rowIndex == 0) { // 把第1列第0行和第2列第0行的单元格隐去 return { display: "none" }; } } if ((columnIndex == 0) & (rowIndex == 0)) { // 把第0列第0行的单元格横向延伸,补上刚刚隐去的单元格位置,并上个色 this.$nextTick(() => { document.querySelector(`.${column.id}`).setAttribute("colspan", "3"); }); return { background: "pink" }; } /** * 合并:重要信息--->公开重要信息--->爱好性格单元格 【通过单元格的文字内容来合并】 * */ if (column.label == "性格") { return { display: "none" }; } if (column.label == "爱好&性格") { this.$nextTick(() => { document.querySelector(`.${column.id}`).setAttribute("colspan", "2"); }); return { background: "orange" }; // 不加这个也行,加了只是为了更好区分 } /** * 重要!重要!重要! * 我们想要合并表头的单元格,需要先找到对应单元格 * 可以通过列column对象的label或者行与列索引来找到,找到以后进行隐藏或合并 * 也可以遍历行row数组找,不过会麻烦一些,个人建议通过column来找 * */ // 通过column找 if (column.label == "技能") { return { background: "#baf" }; } // 通过row找 for (const item of row) { if (item.label == "重要信息") { this.$nextTick(() => { document.querySelector(`.${item.id}`).style.background = "#ea66a6"; }); break; } } }, }, }; </script>
还可以,直接通过column.label找到对应单元格,然后进行合并单元格操作,不使用rowIndex和columnIndex了
这种方式,在某些情况下,会更加方便
但无论哪种方式,本质思路都是先找到单元格,再进行合并相关操作
headerCellStyle({ row, column, rowIndex, columnIndex }) { // 第一部分的合并 if (column.label == "年龄") { return { display: "none" }; } if (column.label == "家乡") { return { display: "none" }; } if (column.label == "基本信息(姓名、年龄、家乡)") { this.$nextTick(() => { document.querySelector(`.${column.id}`).setAttribute("colspan", "3"); }); return { background: "pink" }; } // 第二部分的合并 if (column.label == "性格") { return { display: "none" }; } if (column.label == "爱好&性格") { this.$nextTick(() => { document.querySelector(`.${column.id}`).setAttribute("colspan", "2"); }); return { background: "orange" }; } },
总结
到此这篇关于vue中table表头单元格合并(附单行、多级表头代码)的文章就介绍到这了,更多相关vue table表头单元格合并内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
vue中this.$http.post()跨域和请求参数丢失的解决
这篇文章主要介绍了vue中this.$http.post()跨域和请求参数丢失的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-04-04Vue路由对象属性 .meta $route.matched详解
今天小编就为大家分享一篇Vue路由对象属性 .meta $route.matched详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2019-11-11
最新评论