el-tabs 页签中表格组件宽度闪动问题解决方案

背景

项目中有一个表格组件用在页签组件下,在页签切换时表格的宽度会出现跳动,具体表现就是表格会"闪"一下,示例代码如下:

html 复制代码
<el-tabs type="card" v-model="activeName">
    <el-tab-pane label="系统配置" name="system"><systemData /></el-tab-pane>
    <el-tab-pane label="流程管理" name="flow"><flow /></el-tab-pane>
</el-tabs>

问题定位

  1. 通过观察表格的元素,可以看到表格的宽度发生了变化,为了进一步定位触发宽度改变的代码位置,采用 dom 属性断点来观察代码执行
  1. 执行页签切换动作,复现问题,观察代码执行状态和运行堆栈
  1. 通过断点可以得到以下几个关键信息点:
    1. 页签切换时,触发了 resizeListener ,进而触发宽度计算函数
    2. resizeListener 触发 doLayout 的逻辑是宽度或高度发生变化
    3. 由上述分析可以得到问题的根本原因是页签切换时 el-panel 被设置为 display:none 使得容器宽度坍缩为 "0" ,触发了 resizeListener,页签切换回来时宽度恢复,这里再次被触发,所以宽度会在切换的瞬间发生跳动

解决方案

通过上述分析,我们可以知道根本原因就是页签切换时容器的宽度和高度坍缩为"0"导致的问题,从源码中我们也可以看到高度的判断有一个 !this.height 的判断,但是宽度没有加上这个判断,我的解决方案是在组件的 mounted 钩子中加一段代码重写 el-table 内部的 resizeListener 方法解决这个BUG,示例代码如下:

html 复制代码
<template>
    <el-table ref="elTable"></el-table>
</template>
<script>
export default {
    mounted() {
        // 解决 el-table 在容器宽度为0时,宽度闪烁的问题
        const _tableResizeListener = this.$refs.eltable.resizeListener
        this.$refs.eltable.resizeListener = function () {
          // 当元素的宽度和高度不为 0 时才触发 resize
          if (!this.$el || !this.$el.offsetWidth || !this.$el.offsetHeight) {
            return
          }
          _tableResizeListener.call(this);
        }
        this.$refs.eltable.unbindEvents()
        this.$refs.eltable.bindEvents()
    }
}
</script>

总结

这个问题的排查其实还比较顺利,因为一开始断点后基本就定位到问题了,后面就是针对性解决问题,我这里没有直接改 elment-ui 的源码一个原因是官方已经停止维护,提 PR 也无济于事,在代码中通过这种打补丁的方式来解决问题是最快捷也最有效的方式,同时也不破坏原有的组件框架。

相关推荐
很晚很晚了1 天前
纯前端转全栈 Day 1:我从第一个 NestJS 接口开始
前端
Lee川1 天前
从零解剖一个 AI Agent Tool是如何实现的
前端·人工智能·后端
wangruofeng1 天前
Playwright 深度调研:为什么它成了浏览器自动化的新底座
前端·测试
李白的天不白1 天前
SSR服务端渲染
前端
卷帘依旧1 天前
SSE(Server-Sent Events)完全指南
前端
码云之上1 天前
万星入坞:我们如何用三层插件体系干掉巨石应用
前端·架构·前端框架
kyriewen1 天前
一口气讲清楚 Monorepo、Turborepo、pnpm、Changesets 到底是什么?
前端·架构·前端工程化
IT_陈寒1 天前
React性能优化踩的坑,这个错你可能也会犯
前端·人工智能·后端
zhangxingchao1 天前
AI应用开发三:RAG技术与应用
前端·人工智能·后端
摘星小杨1 天前
如何在前端循环调取接口,实时查询数据
开发语言·前端·javascript