0


el-table表格动态合并行、合并行列及详解

📝 个人简介

⭐ 个人主页:我是段段🙋‍
🍊 博客领域:编程基础、前端💻
🍅 写作风格:干货!干货!都是干货!
🍑 精选专栏:Vue
🛸 支持段段:点赞👍、收藏⭐、留言💬

文章目录

前言

在写项目的时候有时候会经常遇到把行和列合并起来的情况,因为有些数据是重复渲染的,不合并行列会使表格看起来非常的混乱,如下:
在这里插入图片描述

而我们想要的数据是下面这种情况,将重复的行进行合并,使表格看起来简单明了,如下:
在这里插入图片描述

1、合并行

所谓的合并行就是将多行相同的数据变成一行来显示,直接上代码,页面的布局比较简单

<template><divclass="table"><el-table:data="tableData":span-method="objectSpanMethod"borderstyle="width: 100%"><el-table-columnprop="time"label="时间"></el-table-column><el-table-columnprop="grade"label="年级"></el-table-column><el-table-columnprop="name"label="姓名"></el-table-column><el-table-columnprop="subjects"label="科目"></el-table-column><el-table-columnprop="score"label="成绩"></el-table-column></el-table></div></template>
span-method

是el-table上属性,其值是一个

函数

,objectSpanMethod方法是用来处理合并行的返回值,tableData数据如下:

tableData:[{time:'2020-08-10',grade:'三年二班',name:'小明',subjects:'语文',score:80},{time:'2020-08-10',grade:'三年二班',name:'小明',subjects:'数学',score:80},{time:'2020-08-10',grade:'三年一班',name:'小雷',subjects:'语文',score:70},{time:'2020-08-10',grade:'三年一班',name:'小雷',subjects:'数学',score:80},{time:'2020-08-11',grade:'三年三班',name:'小花',subjects:'语文',score:60},{time:'2020-08-11',grade:'三年三班',name:'小花',subjects:'数学',score:60},],mergeObj:{},// 用来记录需要合并行的下标mergeArr:['time','grade','name','subjects','score']// 表格中的列名

首先需要对数据就行处理,就是比较当前行与上一行的值是否相等(如果是第一行数据,直接将值赋值为1)

mounted

中调用数据初始化数据的方法,如下:

mounted(){this.getSpanArr(this.tableData);}
// getSpanArr方法getSpanArr(data){this.mergeArr.forEach((key, index1)=>{let count =0;// 用来记录需要合并行的起始位置this.mergeObj[key]=[];// 记录每一列的合并信息
        data.forEach((item, index)=>{// index == 0表示数据为第一行,直接 push 一个 1if(index ===0){this.mergeObj[key].push(1);}else{// 判断当前行是否与上一行其值相等 如果相等 在 count 记录的位置其值 +1 表示当前行需要合并 并push 一个 0 作为占位if(item[key]=== data[index -1][key]){this.mergeObj[key][count]+=1;this.mergeObj[key].push(0);}else{// 如果当前行和上一行其值不相等 
                    count = index;// 记录当前位置 this.mergeObj[key].push(1);// 重新push 一个 1}}})})}

数据处理好之后就可以调用objectSpanMethod方法了,如下:

// objectSpanMethod方法// 默认接受四个值 { 当前行的值, 当前列的值, 行的下标, 列的下标 }objectSpanMethod({ row, column, rowIndex, columnIndex }){// 判断列的属性if(this.mergeArr.indexOf(column.property)!==-1){// 判断其值是不是为0 if(this.mergeObj[column.property][rowIndex]){return[this.mergeObj[column.property][rowIndex],1]}else{// 如果为0则为需要合并的行return[0,0];}}}

合并后的结果就是我们想要的形式:
在这里插入图片描述
合并行完整的代码如下:

<template><divclass="table"><el-table:data="tableData":span-method="objectSpanMethod"borderstyle="width: 100%"><el-table-columnprop="time"label="时间"></el-table-column><el-table-columnprop="grade"label="年级"></el-table-column><el-table-columnprop="name"label="姓名"></el-table-column><el-table-columnprop="subjects"label="科目"></el-table-column><el-table-columnprop="score"label="成绩"></el-table-column></el-table></div></template><script>exportdefault{name:'Table',data(){return{tableData:[{time:'2020-08-10',grade:'三年二班',name:'小明',subjects:'语文',score:80},{time:'2020-08-10',grade:'三年二班',name:'小明',subjects:'数学',score:80},{time:'2020-08-10',grade:'三年一班',name:'小雷',subjects:'语文',score:70},{time:'2020-08-10',grade:'三年一班',name:'小雷',subjects:'数学',score:80},{time:'2020-08-11',grade:'三年三班',name:'小花',subjects:'语文',score:60},{time:'2020-08-11',grade:'三年三班',name:'小花',subjects:'数学',score:60},],mergeObj:{},mergeArr:['time','grade','name','subjects','score'],};},methods:{getSpanArr(data){this.mergeArr.forEach((key, index1)=>{let count =0;// 用来记录需要合并行的起始位置this.mergeObj[key]=[];// 记录每一列的合并信息
                data.forEach((item, index)=>{// index == 0表示数据为第一行,直接 push 一个 1if(index ===0){this.mergeObj[key].push(1);}else{// 判断当前行是否与上一行其值相等 如果相等 在 count 记录的位置其值 +1 表示当前行需要合并 并push 一个 0 作为占位if(item[key]=== data[index -1][key]){this.mergeObj[key][count]+=1;this.mergeObj[key].push(0);}else{// 如果当前行和上一行其值不相等 
                            count = index;// 记录当前位置 this.mergeObj[key].push(1);// 重新push 一个 1}}})})},// 默认接受四个值 { 当前行的值, 当前列的值, 行的下标, 列的下标 }objectSpanMethod({ row, column, rowIndex, columnIndex }){// 判断列的属性if(this.mergeArr.indexOf(column.property)!==-1){// 判断其值是不是为0 if(this.mergeObj[column.property][rowIndex]){return[this.mergeObj[column.property][rowIndex],1]}else{// 如果为0则为需要合并的行return[0,0];}}}},mounted(){this.getSpanArr(this.tableData);}};</script><stylelang="stylus"scoped>
.table 
    height 100vh
    width 100%
    padding 40px
    box-sizing border-box
    /deep/ .el-table__body tr:hover > td
        background-color: #fff;</style>

2、合并行列

调整下数据,如下:

tableData:[{time:'2020-08-10',grade:'三年二班',name:'小明',subjects:'语文',score:80},{time:'2020-08-10',grade:'三年二班',name:'小明',subjects:'数学',score:80},{time:'2020-08-10',grade:'总成绩',name:'总成绩',subjects:'总成绩',score:160},{time:'2020-08-10',grade:'三年一班',name:'小雷',subjects:'语文',score:70},{time:'2020-08-10',grade:'三年一班',name:'小雷',subjects:'数学',score:80},{time:'2020-08-10',grade:'总成绩',name:'总成绩',subjects:'总成绩',score:150},{time:'2020-08-11',grade:'三年三班',name:'小花',subjects:'语文',score:60},{time:'2020-08-11',grade:'三年三班',name:'小花',subjects:'数学',score:60},{time:'2020-08-11',grade:'总成绩',name:'总成绩',subjects:'总成绩',score:120}],

可以看到上面的数据多了一行总成绩,现在的数据在页面显示效果如下:

在这里插入图片描述

可以看到总成绩的三个列并没有合并,并不是我们想要的效果,所以需要换一种思路来处理数据

页面的布局也有所调整,如下:

<template><divclass="table"><el-table:data="tableData":span-method="objectSpanMethods"borderstyle="width: 100%"><templatev-for="cols in colConfigs"><!-- 无需合并的列 --><el-table-columnv-if="cols.type === 'label' && !cols.children":key="cols.prop":prop="cols.prop":label="cols.label"></el-table-column><!-- 需要合并的列 --><templatev-else-if="cols.type === 'label' && cols.children"><el-table-columnv-for="children in cols.children":key="children.prop":prop="children.prop":label="children.label"/></template></template></el-table></div></template>

tableData中的数据就是上面调整后的,还需要声明的变量如下:

// 表格的信息 需要合并的需要放在 children 中colConfigs:[{type:'label',children:[{prop:'time',label:'时间'},{prop:'grade',label:'年级'},{prop:'name',label:'姓名'},{prop:'subjects',label:'科目'},{prop:'score',label:'成绩'}]}],// 需要合并的行列信息mergeCols:[{index:0,name:'time'},{index:1,name:'grade'},{index:2,name:'name'},{index:3,name:'subjects'},{index:4,name:'score'},],// 用来记录每一个单元格的下标tableMergeIndex:[],

首先也需要处理数据,在

mounted

中调用数据初始化数据的方法,如下:

mounted(){if(this.mergeCols.length >0){this.newTableMergeData();}}
// newTableMergeData方法newTableMergeData(){for(let i =0; i <this.tableData.length; i++){for(let j =0; j <this.mergeCols.length; j++){// 初始化行、列坐标信息let rowIndex =1;let columnIndex =1;// 比较横坐标左方的第一个元素if(j >0&&this.tableData[i][this.mergeCols[j]['name']]===this.tableData[i][this.mergeCols[j -1]['name']]){
                columnIndex =0;}// 比较纵坐标上方的第一个元素if(i >0&&this.tableData[i][this.mergeCols[j]['name']]===this.tableData[i -1][this.mergeCols[j]['name']]){
                rowIndex =0;}// 比较横坐标右方元素if(columnIndex >0){
                columnIndex =this.onColIndex(this.tableData[i], j, j +1,1,this.mergeCols.length);}// 比较纵坐标下方元素if(rowIndex >0){
                rowIndex =this.onRowIndex(this.tableData, i, i +1,1,this.mergeCols[j]['name']);}let key =this.mergeCols[j]['index']+'_'+ i;this.tableMergeIndex[key]=[rowIndex, columnIndex];}}},/**
  * 计算列坐标信息
  * data 单元格所在行数据
  * index 当前下标
  * nextIndex 下一个元素坐标
  * count 相同内容的数量
  * maxLength 当前行的列总数
  */onColIndex(data, index, nextIndex, count, maxLength){// 比较当前单元格中的数据与同一行之后的单元格是否相同if(nextIndex < maxLength && data[this.mergeCols[index]['name']]=== data[this.mergeCols[nextIndex]['name']]){returnthis.onColIndex(data, index,++nextIndex,++count, maxLength);}return count;},/**
  * 计算行坐标信息
  * data 表格总数据
  * index 当前下标
  * nextIndex 下一个元素坐标
  * count 相同内容的数量
  * name 数据的key
  */onRowIndex(data, index, nextIndex, count, name){// 比较当前单元格中的数据与同一列之后的单元格是否相同if(nextIndex < data.length && data[index][name]=== data[nextIndex][name]){returnthis.onRowIndex(data, index,++nextIndex,++count, name);}return count;}

数据处理好之后就可以调用objectSpanMethods方法了,如下:

objectSpanMethods({ row, column, rowIndex, columnIndex }){let key = columnIndex +'_'+ rowIndex;if(this.tableMergeIndex[key]){returnthis.tableMergeIndex[key];}}

实现的效果图如下:

在这里插入图片描述
合并行列的完整代码如下:

<template><divclass="table"><el-table:data="tableData":span-method="objectSpanMethods"borderstyle="width: 100%"><templatev-for="cols in colConfigs"><!-- 无需合并的列 --><el-table-columnv-if="cols.type === 'label' && !cols.children":key="cols.prop":prop="cols.prop":label="cols.label"></el-table-column><!-- 需要合并的列 --><templatev-else-if="cols.type === 'label' && cols.children"><el-table-columnv-for="children in cols.children":key="children.prop":prop="children.prop":label="children.label"/></template></template></el-table></div></template><script>exportdefault{name:'Table',data(){return{tableData:[{time:'2020-08-10',grade:'三年二班',name:'小明',subjects:'语文',score:80},{time:'2020-08-10',grade:'三年二班',name:'小明',subjects:'数学',score:80},{time:'2020-08-10',grade:'总成绩',name:'总成绩',subjects:'总成绩',score:160},{time:'2020-08-10',grade:'三年一班',name:'小雷',subjects:'语文',score:70},{time:'2020-08-10',grade:'三年一班',name:'小雷',subjects:'数学',score:80},{time:'2020-08-10',grade:'总成绩',name:'总成绩',subjects:'总成绩',score:150},{time:'2020-08-11',grade:'三年三班',name:'小花',subjects:'语文',score:60},{time:'2020-08-11',grade:'三年三班',name:'小花',subjects:'数学',score:60},{time:'2020-08-11',grade:'总成绩',name:'总成绩',subjects:'总成绩',score:120}],// 表格的信息 需要合并的需要放在 children 中colConfigs:[{type:'label',children:[{prop:'time',label:'时间'},{prop:'grade',label:'年级'},{prop:'name',label:'姓名'},{prop:'subjects',label:'科目'},{prop:'score',label:'成绩'}]},// { type: 'label', prop: 'age', label: '年龄' }],// 需要合并的行列信息 index必须是table表格对应的下标 不能随意修改mergeCols:[{index:0,name:'time'},{index:1,name:'grade'},{index:2,name:'name'},{index:3,name:'subjects'},{index:4,name:'score'},// { index: 5, name: 'age' }],// 用来记录每一个单元格的下标tableMergeIndex:[],};},methods:{objectSpanMethods({ row, column, rowIndex, columnIndex }){let key = columnIndex +'_'+ rowIndex;if(this.tableMergeIndex[key]){returnthis.tableMergeIndex[key];}},newTableMergeData(){for(let i =0; i <this.tableData.length; i++){for(let j =0; j <this.mergeCols.length; j++){// 初始化行、列坐标信息let rowIndex =1;let columnIndex =1;// 比较横坐标左方的第一个元素if(j >0&&this.tableData[i][this.mergeCols[j]['name']]===this.tableData[i][this.mergeCols[j -1]['name']]){
                        columnIndex =0;}// 比较纵坐标上方的第一个元素if(i >0&&this.tableData[i][this.mergeCols[j]['name']]===this.tableData[i -1][this.mergeCols[j]['name']]){
                        rowIndex =0;}// 比较横坐标右方元素if(columnIndex >0){
                        columnIndex =this.onColIndex(this.tableData[i], j, j +1,1,this.mergeCols.length);}// 比较纵坐标下方元素if(rowIndex >0){
                        rowIndex =this.onRowIndex(this.tableData, i, i +1,1,this.mergeCols[j]['name']);}let key =this.mergeCols[j]['index']+'_'+ i;this.tableMergeIndex[key]=[rowIndex, columnIndex];}}},/**
         * 计算列坐标信息
         * data 单元格所在行数据
         * index 当前下标
         * nextIndex 下一个元素坐标
         * count 相同内容的数量
         * maxLength 当前行的列总数
         */onColIndex(data, index, nextIndex, count, maxLength){// 比较当前单元格中的数据与同一行之后的单元格是否相同if(nextIndex < maxLength && data[this.mergeCols[index]['name']]=== data[this.mergeCols[nextIndex]['name']]){returnthis.onColIndex(data, index,++nextIndex,++count, maxLength);}return count;},/**
         * 计算行坐标信息
         * data 表格总数据
         * index 当前下标
         * nextIndex 下一个元素坐标
         * count 相同内容的数量
         * name 数据的key
         */onRowIndex(data, index, nextIndex, count, name){// 比较当前单元格中的数据与同一列之后的单元格是否相同if(nextIndex < data.length && data[index][name]=== data[nextIndex][name]){returnthis.onRowIndex(data, index,++nextIndex,++count, name);}return count;}},mounted(){if(this.mergeCols.length >0){this.newTableMergeData();}}};</script><stylelang="stylus"scoped>
.table 
    height 100vh
    width 100%
    padding 40px
    box-sizing border-box
    /deep/ .el-table__body tr:hover > td
        background-color: #fff;</style>

如果用不想合并的行需要在

colConfigs

中调整,如下:

// 增加一个年龄属性 但是不进行合并colConfigs:[{type:'label',children:[{prop:'time',label:'时间'},{prop:'grade',label:'年级'},{prop:'name',label:'姓名'},{prop:'subjects',label:'科目'},{prop:'score',label:'成绩'}]},{type:'label',prop:'age',label:'年龄'}]

效果图如下:

在这里插入图片描述
如果想要合并,需要在

mergeCols

中添加数据,如下:

mergeCols:[{index:0,name:'time'},{index:1,name:'grade'},{index:2,name:'name'},{index:3,name:'subjects'},{index:4,name:'score'},{index:5,name:'age'}// 添加需要合并的age列信息 注意index的值],

新添加的属性合并后效果图如下:
在这里插入图片描述
以上就是el-table表格合并行列的内容,有不懂的地方欢迎留言讨论~

标签: javascript 前端 html

本文转载自: https://blog.csdn.net/qq_43432158/article/details/126402868
版权归原作者 我是段段 所有, 如有侵权,请联系我们删除。

“el-table表格动态合并行、合并行列及详解”的评论:

还没有评论