提示:由于大家使用的Vue3和Element Plus的版本不同,所以可能会出现一些差异
前言
提示:Element Plus的官网链接很卡,可能需要富强
最近在做一些数据展示类型的项目,其中有一个表格需求把我吓懵了,大概是这样的,表格的每一行数据可能会有子集,父级行要与子集行用颜色区分开来,这个好处理,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 方法来监听表头的点击操作,因为代码比较多我就不粘贴出来了,我只说一下点击之后我们要做什么。首先点击表头后,我们能拿到的有效数据是label 和prop (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风味):传送门
|