被产品吐槽后,我用最笨的方法解决 vxe-table 的白屏问题~

大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心。

背景

事情是这样的,最近团队为了优化用户体验,做了很多针对性的措施,但是有一个小问题,一直卡着。那就是我们使用 vxe-table 这个表格组件库,但是发现他在数据量大的情况下,拖动滚动条 会有白屏现象

其实这个问题可大可小,但是身为一个菜鸟级别前端,肯定是想挑战自我,更进一步成为入门级别前端!!!于是我开始着手解决这个问题~

跟电脑性能有关?

我的电脑是 Macbook pro 19款,性能问题应该不至于那么严重,试了一下同事的 M1,也是照样有这个问题,Windows 也有这个问题,我试过的电脑,拖动滚动条都会有白屏现象,所以你们可别叫我换电脑哦~

跟虚拟滚动有关吗?

一开始我觉得是不是因为默认开启了虚拟滚动,所以在滚动的时候需要去计算下一次的渲染,计算是需要过程的,所以导致了短暂的白屏,所以我马上把虚拟滚动关了~~ 但结果还是老样子,所以排除虚拟滚动这个原因~~

虽然虚拟滚动也会导致白屏,但是vxe-table预渲染的功能,所以问题不大

跟表格组件有关?

那是不是只有vxe-table有这个现象呢?其实不止是 vxe-table,我去看了市面上那些表格组件其实都会有这个现象,我看了包括(我是在 Mac 上试的):

  • Surely Vue: 号称高性能表格,Mac有白屏,Windows无白屏,不开源
  • Ant-Design Table: 很火的组件库,没解决白屏问题
  • Element Table: 很火的组件库,没解决白屏问题

无一例外,都存在白屏现象

跟框架有关系?

那跟框架有关系吗?难道我换个框架就好了?要不,我直接不用框架,我用原生好不好?于是我直接新建一个html文件,里面我写了 10000 条数据

html 复制代码
<body>
    <div>
      <div>林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端</div>
      <div>林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端</div>
      <div>林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端--林三心菜鸟级别前端</div>
      // ... 10000 条
    </div>

拖动了,结果也是会有白屏现象,只不过少了框架+组件库这一层,原生的白屏现象会比较轻一些,但是还是没有解决问题

跟浏览器有关?

那现在只剩浏览器这个因素了,其实vxe-tableissue中有人反映了谷歌浏览器版本问题

注:我们用户大部分都是谷歌浏览器,所以我暂时先考虑谷歌浏览器

确实跟谷歌浏览器的版本有关,我现在的版本是115的,我换了95版本的谷歌浏览器就没有这个问题了,但是不可能让用户去用旧版本浏览器吧,所以问题还是得解决~

vxe-table 的固定列滚动

我看到了一个vxe-table的官方例子,是一个固定列的例子,我发现当表格拥有固定列的时候,拖动滚动条,固定列会有白屏现象,但是主表格并不会有白屏现象,如下:

我看了源码,我理解应该是固定列(固定列其实也是一个表格,我称为副表格)的滚动,带动了主表格的滚动,所以主表格的滚动是被动的,导致主表格滚动速率没有那么快,所以白屏现象就消失了~

审查元素,看看,其实固定列是一个表格(副表格),我们拖动的滚动条是副表格的滚动条

注:滚动白屏现象,其实跟滚动速率也有关,你慢慢滚就不会有白屏,滚得快就会有。拖动滚动条就是一个滚得快的操作~

笨方法 解决 大难题

回到正题,刚刚说了,有了固定列,那么当你拖动滚动条时,虽然滚动的很快,但是主表格是被动滚动的,所以速率不会那么快,也就不会有白屏现象

那,我能不能自己塞一个固定列进表格里?这样拖动滚动条时,其实就是拖动我塞进去的这个副表格,但是这个固定列需要具备以下条件

  • 不影响表格列的原始数据
  • 不能跟用户自定义的固定列冲突
  • 必须是一个不可见的固定列,这样用户才能无感知

于是我进行了修改源码的操作

想自己调试的兄弟,可以把vxe-table的源码从 node_modules 中拖到 src 下,然后去引入,去进行调试,改 node_modules 中代码去调试比较麻烦,因为 node_modules 是在热更新监听范围之外的~

我设想是传入一个参数,去开启我这个优化,我选择在params中传入自定义参数scrollFollow

paramsvxe-table自带的参数,可以让我们传额外参数进去~

html 复制代码
  <vxe-table
    ...
    :params="{
      scrollFollow: true,
    }"
  ></vxe-table>

修改 table.js

我的vxe-table版本是4.4.2

刚刚说了,我需要塞一个不可见的、不冲突的固定列进表格中,那么我需要进到这个文件中去修改

路径:vxe-table/es/table/src/table.js

我们先要引入一个方法vxe-table 内置的方法 createColumn,想要创建一个列,就得用这个方法,固定列也不例外~

js 复制代码
import { getRowUniqueId, clearTableAllStatus, getRowkey, getRowid, rowToVisible, colToVisible, getCellValue, setCellValue, handleFieldOrColumn, toTreePathSeq, restoreScrollLocation, restoreScrollListener, createColumn } from './util';

接着我们需要在parseColumns 中去塞入固定列,在这个方法里去塞入,是因为不想污染表格的columns数据源,这个rightList就是原本代码逻辑计算出的最终右固定列的数据,我们需要判断他有没有长度,有长度说明用户自定义了固定列,没有长度则说明用户没有自定义固定列

  • 用户自定义了固定列,那么我们就不塞了
  • 用户没有自定义固定列,那我们就塞一个不可见的固定列进去
js 复制代码
if (scrollFollow && rightList && !rightList.length) {
  rightList.push(
    createColumn(
      $xetable,
      {
        align: undefined,
        cellRender: undefined,
        cellType: undefined,
        className: undefined,
        colId: undefined,
        contentRender: undefined,
        editRender: undefined,
        exportMethod: undefined,
        field: '',
        filterMethod: undefined,
        filterMultiple: true,
        filterRecoverMethod: undefined,
        filterRender: undefined,
        filterResetMethod: undefined,
        filters: null,
        fixed: 'right', // 右固定列
        footerAlign: undefined,
        footerClassName: undefined,
        footerExportMethod: undefined,
        formatter: undefined,
        headerAlign: undefined,
        headerClassName: undefined,
        maxWidth: undefined,
        minWidth: undefined,
        params: undefined,
        resizable: null,
        showFooterOverflow: null,
        showHeaderOverflow: null,
        showOverflow: null,
        sortBy: undefined,
        sortType: undefined,
        sortable: false,
        title: '',
        titleHelp: undefined,
        titlePrefix: undefined,
        treeNode: false,
        type: undefined,
        visible: true,
      },
      {
        renderCell: () => null, // 空
        renderHeader: () => null, // 空
      },
    ),
  )
}

但是我们平时在用表格的时候,会发现,固定列会有消失的时候,比如现在水平滚动没有滚动到最右边时,固定列是在的,也就是副表格是在的,我们滚动的时候主表格不会白屏

但是如果水平滑到最右边,我们发现固定列跟主表格融为一体了,也就是副表格不在了,那么这个时候去拖动滚动条,拖的就是主表格的滚动条,白屏现象又出现了!!!

我们可不能让这种事发生,我们可以看源码,可以看到渲染固定列是有条件的!

但是,我想要我塞进去的固定列,时时刻刻都渲染,那咋办呢?我可以给固定列的渲染再加一个条件!保证了我塞进去的固定列,时时刻刻渲染!保证我拖动的滚动条时时刻刻都是副表格的!

效果

效果达成了!滚动的时候白屏现象没有喽!!!!

小问题修复(可不改,有需要就改)

发现一个小问题,改源码之后,导致在动态减列 的时候,会有一个空白列展示出来了。

其实这个列是原本没改源码前就有的,只不过那时候是不显示出来的,现在改了源码,导致这个列展示出来了,那其实我们可以让他不展示出来即可

路径:vxe-table/es/table/src/table.js

想要隐藏列,我们需要隐藏两个东西

  • header:表头
  • body:表体

可以各自传一个自定义参数hiddenLastCol进去

接下来我们要去headerbody组件中,去接受这个参数,并改变样式去隐藏

路径:vxe-table/es/table/src/body.js

路径:vxe-table/es/header/src/header.js

最后需要去定义col--hidden的样式就行啦!

路径:vxe-table/lib/style.css

效果

现在空白列也不会出现啦~

滚轮白屏问题 -> mode: 'wheel'

上面是已经解决了拖动滚动条的白屏的问题,但是其实有的电脑硬件比较差,滚动滚动居然也会有白屏现象吗,这个时候可以设置vxe-tablescroll-y="{ mode: 'wheel' }"去解决这个问题~

遗留问题 && 声明

我的笨方法就是自己塞一个固定列举进去,让主表格滚动白屏问题能得到解决,但是其实固定列自己的滚动白屏还是没有解决,所以我的解法只适用于这些情况

  • 有固定列的表格,但是不讲究固定列的白屏问题,只在意主表格的白屏问题
  • 不需要固定列的表格

当然我只是提供了一个解决思路而已,并且这个思路可以用在很多表格中,不止是vxe-table,各位大佬有什么更好的解法的话,欢迎可以评论区留言,大家一起讨论!!!

结语 & 加学习群 & 摸鱼群

我是林三心

  • 一个待过小型toG型外包公司、大型外包公司、小公司、潜力型创业公司、大公司的作死型前端选手;
  • 一个偏前端的全干工程师;
  • 一个不正经的掘金作者;
  • 一个逗比的B站up主;
  • 一个不帅的小红书博主;
  • 一个喜欢打铁的篮球菜鸟;
  • 一个喜欢历史的乏味少年;
  • 一个喜欢rap的五音不全弱鸡

如果你想一起学习前端,一起摸鱼,一起研究简历优化,一起研究面试进步,一起交流历史音乐篮球rap,可以来俺的摸鱼学习群哈哈,点这个,有7000多名前端小伙伴在等着一起学习哦 --> 摸鱼沸点

相关推荐
F-2H23 分钟前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
gqkmiss1 小时前
Chrome 浏览器插件获取网页 iframe 中的 window 对象
前端·chrome·iframe·postmessage·chrome 插件
m0_748247553 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
m0_748255024 小时前
前端常用算法集合
前端·算法
真的很上进4 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web130933203984 小时前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_2344 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1235 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~6 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语6 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js