element-ui 表格组件固定列,切换移动端视图后无法对齐的解决方案

3,272 阅读3分钟

前言

前段时间,在使用 element-ui 时,发现它的 table 组件,在切换成移动端(通过F12切换视窗)后,其固定列(即 fixed 列)展示异常的问题。

一开始以为是使用的 element-ui 版本低了(2.13.2),后升级到最新版(2.15.13)后,问题依然存在。没办法,只能自己看看源码找找问题原因。

以下是解决问题的过程记录,仅供同样踩坑的同学参考。

问题场景描述

PC端正常效果

element-uitable 组件(以下简称 table 组件),在设定行属性为 fixed 时,PC 端下具有以下页面效果。

由图可见,固定列(fixed 列)悬浮于表格之上,滚动条居于右方和下方,此时滚动条和固定列展示正常。

注:为了方便展示横向和纵向滚动条的效果,故选取文档页流体高度一栏的效果。

移动端正常效果

table 组件,在设定行属性为 fixed 时,在移动端下具有以下页面效果。

由图可见,固定列(fixed 列)悬浮于表格之上,相较于 PC 端,移动端滚动条较细(移动端滚动条默认样式),横向滚动条居于下方,被固定列遮挡,纵向滚动条亦被固定列遮挡,此时滚动条和固定列的展示也还算正常。

注:为了方便展示横向和纵向滚动条的效果,故选取文档页流体高度一栏的效果。

PC端切换移动端异常

table 组件,在设定行属性为 fixed 时,在 PC 端初始化,后切换到移动端时,会出现以下异常情况。

底部和右侧存在滚动条的场合,固定列的底部和右侧不会贴紧表格边缘,会留一段空隙出来。固定列的下沿和右侧部分空间会被吃掉(展示不全)。

注:为了方便展示横向和纵向滚动条的效果,故选取文档页流体高度一栏的效果。

问题分析

页面从 PC 端切换到移动端时,滚动条的宽度从 17px 减少为细滚动条(具体宽度看移动端操作系统和浏览器,这里具体数值无影响,故不做赘述),而固定列的宽高没有主动自适应,导致了固定列的宽高依然是基于 17px 滚动条的展示。

注:如果设置了 height 的话,这里会是 height

源码分析

table.vue 组件中,可以找到固定列的对应样式

查看代码不难发现,不管是 fixedBodyHeight 还是 bodyWidth 都跟 this.layout.gutterWidth 有关

this.layout.gutterWidth 的取值则来自获取滚动条宽度(至于获取滚动条宽度的具体逻辑并不需要关心,element-ui 已经封装了方法),但是 this.layout.gutterWidth 的赋值只在初始化时进行,而不会根据视图的变化而动态更新,由此,原因找到了。

解决方案

理论上,想要让 table 组件在切换视图时,固定列对齐到底部和右侧,只需要监听视图变化,及时更新滚动条的宽度就可以了。

直接上代码

import scrollbarWidth from 'element-ui/src/utils/scrollbar-width';

// vue 实例中
watch: {
  // 监听视图变化事件的回调
  // 可以使用 window.addEventListener('resize') 或者 resizeObserver 等方法监听,这里不再赘述
  resize() {
    this.$nextTick(()=>{
      // 手动获取滚动条宽度
      this.$refs.elTable.layout.gutterWidth = scrollbarWidth();
      // 手动更新高度
      this.$refs.elTable.layout.updateElsHeight();
    })
  }
},

修复后的效果

固定列撑满到底部和右侧,横向滚动条悬浮于普通列上固定列下

最后

修复的 element-ui 版本为 2.13.2,最新版应该也可以使用该方案进行修复。

尽管最后实现上只是短短两行代码,当实际上排查问题+查阅源码+调试还是要花不少时间的。

如果文章对你有帮助,麻烦顺手点个赞。

如果要转载,请注明此原文链接。

谢谢!