前言
前段时间,在使用 element-ui 时,发现它的 table 组件,在切换成移动端(通过F12切换视窗)后,其固定列(即 fixed 列)展示异常的问题。
一开始以为是使用的 element-ui 版本低了(2.13.2),后升级到最新版(2.15.13)后,问题依然存在。没办法,只能自己看看源码找找问题原因。
以下是解决问题的过程记录,仅供同样踩坑的同学参考。
问题场景描述
PC端正常效果
element-ui 的 table 组件(以下简称 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,最新版应该也可以使用该方案进行修复。
尽管最后实现上只是短短两行代码,当实际上排查问题+查阅源码+调试还是要花不少时间的。
如果文章对你有帮助,麻烦顺手点个赞。
如果要转载,请注明此原文链接。
谢谢!