vue3 el-table多级表头收缩扩展的实现

提示:由于大家使用的Vue3和Element Plus的版本不同,所以可能会出现一些差异


前言

提示:Element Plus的官网(https://element-plus.org/zh-CN/)链接很卡,可能需要富强,文章内容已换成国内镜像站点

最近在做一些数据展示类型的项目,其中有一个表格需求把我吓懵了,大概是这样的,表格的每一行数据可能会有子集,父级行要与子集行用颜色区分开来,这个好处理,el-table给我们提供了树形数据与懒加载来处理每一行存在层级的关系,行的颜色可以用table-属性row-class-name来动态绑定颜色;另外是表头,表头有多级,这个官网的多级表头有,除此之外一个多级表头可能还会有子集,并且需要收缩扩展和颜色区分,颜色区分可以用table-属性header-cell-class-name来动态绑定颜色,对于表头存在子集并且可收缩扩展大家听起来可能有点抽象,可以看一下下面的图片:
在这里插入图片描述


提示:以下是本篇文章正文内容,下面案例可供参考

实现逻辑

因为el-table并没有提供表头收缩扩展的功能,所以我的想法是用v-if或者v-show去动态的加载表头,接着是要把表头关联起来,这是一件很头疼的事情,因为我们的每一个表头的数据都是要同级的,一般后端返回的表头数据是长这么样子:

let tableheader = [{
    
    
    label: '表头1',
    children: [{
    
    
        label: '表头1-1',
        children: [{
    
    
            label: '表头1-1-1',
        }]
    }, {
    
    
        label: '表头1-2',
    }]
},
{
    
    
    label: '表头2'
}]

这种树形结构型的数据控制子表头显示隐藏只需要遍历子数组就好,然而我们el-table表头实际需要的数据却是这样的:

let tableheader = [{
    
    
    label: '表头1'
}, {
    
    
    label: '表头1-1'
}, {
    
    
    label: '表头1-1-1'
}, {
    
    
    label: '表头1-2'
}, {
    
    
    label: '表头2'
}]

这就很恶心了,既要把多层数组对象扁平化,又要保证表头的顺序,还要把表头与子表头关联起来。经过一顿折腾,最后把数据格式定了下来,我们先来看一下下面的GIF:
在这里插入图片描述
那么这时的数据则要定义成这样:(由于数据太多我就直接截图了)

  • type、type_children:为了让表头关联起来我定义了type类型来表示父子关系,如果一个表头的type_children不为空,那么说明这个表头存在子集
  • show:表示界面上是否要显示这个表头
  • clickState:用于标识判断当前表头是否被点击过,打开过
  • fixed:表示当表头宽度超出时,左右拉动滚动条的是否需要悬浮固定起来
  • prop、label:el-table固定的,prop用来绑定表行里面的值,label用于表头名称显示
  • width:用来调整表头的宽度
  • color:用来动态绑定表头的颜色
  • row_color:用来动态绑定表行的颜色

在这里插入图片描述
数据定好后我们需要使用到Table 事件header-click方法来监听表头的点击操作,因为代码比较多我就不粘贴出来了,我只说一下点击之后我们要做什么。首先点击表头后,我们能拿到的有效数据是labelprop(property),开始我想用prop,但是当我点击多级表头(也就是上面案例的表头3这种)时返回的prop竟然是undefined,他喵的,原来e-table的这种大表头的第一行是没有绑定prop,所以我放弃了,只能用label来遍历数据了,因为要取唯一值,所以表头的名字就不能一样了。接着就可以用label来查找用户是点击了哪一个表头了,如果是展开表头,就用父表头的type_children去匹对子表头的type,把相关的子表头的show值改成true就好。但是如果是关闭表头,就不仅需要关闭子表头,如果子表头还存在孙子,那就需要深层次的遍历了。

好,看到这里我相信大家就能看懂我Demo里的代码了,我就不多说了


项目效果

因为这是我在el-table上的二次践踏,所以难免会有优缺点,我都说一下让大伙们参谋参谋是否要在自己的项目中使用:

优点:

  • 能实现表头的隐藏收缩,方便用户对比数据
  • 可以动态绑定表头的颜色,视觉效果好,层级分明,立体

缺点:

  • 由于这是饿了么封装了的表格,没有办法添加transition动画,所以收缩扩展会闪烁
  • 另外v-if是用不了,会有一系列的问题,所以当数据多了,不仅第一次加载缓慢,点击表头的展开关闭都会卡很久
  • 后端需要返回有顺序的无层级集合(前端扁平化数组对象有点不科学,因为单个表头可能是多级的大表头),并且要把每一个表头的type类型关联起来,prop的名字也不能相同
  • 表头的名字不能相同

在这里插入图片描述
如果确实是需要用到的,那么绑定完数据后可能需要优化的点我也说一下:

优化:

  • 当数据多了,点击表头必定会卡,所以需要给el-table加上Loading 加载,不然点击表头后可能几秒才反应过来,用户体验会很不好,都不清楚点击了没有
  • 另外添加了Loading 后动画可能会不显示,这时需要在headerClick方法里先开启Loading ,延迟100毫秒后再执行遍历代码,并且使用nextTick等dom渲染完毕后才关闭Loading,至于为什么要这么做才行,是因为加载动画没加载出来前循环逻辑以及之后dom渲染让浏览器吃不消,直接把页面卡到了代码执行完后,这时Loading的状态都要false了,所以看不到
  • 如果实在是不想用定时器延迟执行遍历代码,那么可以用多线程,开一个副线程去处理循环逻辑,这样就能让主线程有充分的时间把Loading动画加载出来,不知道怎么在vue3中使用多线性的可以看这篇文章,反正我是用上了,真香==》传送门
  • 如果行内数据也存在层级(树形数据与懒加载),懒加载是必做不可了,像我这边的项目,单表头都有500多个,直接把Chrome干废了,所以极力推荐你让后端不要一次性把所有表行(包含子集)数据返回,有子集的数据点击后才调用接口去补上这样会好很多
  • 还有一些比较细的,比如说点击表头时的小箭头、完成率达标的百分比标红,调整整列的文字位置等,都可以在我的demo中找到相关代码,具体可以把demo下载下来后看看

项目Demo

有积分的交一下公粮,没有的话到Gitee下载就好

❀CSDN:

table-header-multi-stage(js原味):传送门
table-header-multi-stage-ts(ts风味):传送门

❀Gitee:

table-header-multi-stage(js原味):传送门
table-header-multi-stage-ts(ts风味):传送门

猜你喜欢

转载自blog.csdn.net/weixin_42063951/article/details/125633625