老项目优化之:如何给Avue库的Crud表格组件开启虚拟滚动?写在前面 公司有个老项目用的是Vue2 + avue组件库
写在前面
公司有个老项目用的是Vue2
+ avue
组件库,里面大量的表格使用avue
的crud
组件,在遇到每页200
到500
的大量数据时,全选,分页就会卡卡卡卡个不停
,领导也早早提了优化需求,一直在待办里躺着。
时不时有用户反馈表格卡,再不时表格反映慢,用户对于表格的吐槽不绝于耳。
终于在项目不那么紧张的时间段里,这个老问题再次沉渣又泛起,在我心中激起阵阵涟漪, 久久不能平复,是时候展示真正的技术了
。
看我如何:
十步灭一bug,千里不留行。
开始正文
表格卡顿,又是二次封装的复杂表格,从源码角度优化是一个方案,直接在现有二次封装组件上添加虚拟滚动之类的优化另一个方案;鉴于目测avue组件的复杂性,果断选择走第二条路。
百度必应各种搜索之后确定一个适合Vue2的库:el-table-virtual-scroll。
选定的依据:
- 支持
Vue2
; - 虚拟滚动可以显著提高表格
性能
; - 虚拟滚动组件
全选
;
选定那就开搞吧,看看vue2老牌avue
和el-table-virtual-scroll
之间能擦出怎样的火花呢?
el-table-virtual-scroll基本用法
安装
npm i el-table-virtual-scroll
使用
<virtual-scroll
:data="list"
:item-size="62"
key-prop="id"
@change="(renderData) => virtualList = renderData">
<avue-crud
:option="option"
:table-loading="loading"
:data="virtualList"
:page="page"
:pageTotal="pageTotal"
v-model="form"
ref="crud"
...
/>
</virtual-scroll>
...
import VirtualScroll from 'el-table-virtual-scroll'
export default {
component: {
VirtualScroll
},
data () {
list: [
{
id: 1,
text: 'content'
},
// ...... 省略n条
{
id: 2000,
text: 'content2'
}
],
virtualList: []
}
}
可以看到代码比较简单,通过virtual-scroll
接管el-table
的全部data
数据,然后通过change
事件更新当前需要渲染的数据。
很快啊,遇到了第一个问题
表格没有数据展示,先是推测change
事件没有执行,再发现控制台有报错,大概意思是说没找到el-table
组件, 我不禁要疑惑了,难道二次封装过的el-table
不支持??
随后向上看了几眼el-table-virtual-scroll
源码,让我发现了一个宝藏方法getElTable
,对比文档,发现这个方法正是针对我们这些被封装过的el-table
场景,真实太好了。

为作者点赞哈❤️❤️❤️
当然把这个方法加上看看效果:
getElTable(){
return this.$refs.crud.$refs.table;
},
正当我满心欢喜,以为找到了病根的时候,不出意外的意外就发生了,还是报找不到el-table
实例。
这就尴尬了,在getElTable
里打印this.$refs.crud.$refs.table
时,发现输出undefined
,难受了,是不是avue筛选项太多了导致getElTable
执行的时候表格还没渲染?
怎么办??就这样放弃了?
继续漫无目的地在el-table-virtual-scroll
源码淘宝,发现几个可能有用的方法,initData
、update
、updateData
,那在表格数据初始化的时候调一下这三个方法:
this.data = res.data.list;
this.$refs.virtualScroll.initData();
//this.$refs.virtualScroll.doUpdate()
//this.$refs.virtualScroll.updateData(this.data)
成了,就这么成了?好奇到底是哪个方法成了呢,一个一个尝试发现是initData
方法发挥了效果,查看源码发现initData
里调用了getElTable
,此时拿到el-table也是顺理成章的事了。
开心,以后马上就能结束战斗的时候,遇到了本次优化中最大一个问题?
多选,怎么做?按el-table-virtual-scroll
的例子选择框需要这样实现:
<virtual-column type="selection" width="60"></virtual-column>
...
<script>
import VirtualScroll from 'el-table-virtual-scroll'
import { VirtualColumn } from 'el-table-virtual-scroll'
export default {
components: { VirtualScroll, VirtualColumn },
...
这里用到另一个组件virtual-column
, 也就是el-table-virtual-scroll
需要接管el-table
的多选,这也能理解,毕竟表格开启虚拟滚动只渲染了一部分数据,表格自己全选的话只能选择几个。
问题是avue的columns都是options配置式,虽然支持插槽,试了selection插槽并没有效果
。
咋办?前进
还是后退
这是个问题?
不行,改avue源码吧,脑海里产出这样一个念头,那就死马当活马医好了,先看看源码再说:

找到selection配置项的地方,从外面传入一个selectionComponent='virtual-column'
,当然直接这样写并没有成功,随后在脑海里复盘组件渲染机制,找到了一个可疑点:virtual-column
是局部
引入的,avue在渲染时应该拿不到
局部引入的组件,改成全局引入
试试:
Vue.component("virtual-scroll", VirtualScroll);
Vue.component("virtual-column", VirtualColumn);
完美
!!!运行成功。
至此皆大欢喜,顺利运行,滚动很流畅,全选也很快...
尾声
事了拂衣去,深藏功与名。
最后还遇到一个问题:
重新搜索后,已选项里还包括上一次的选择结果,这也很简单,在搜索时清空选项就可以: this.$refs.virtualScroll.
clearSelection
();
谨以此文纪念那些经历一波三折
最后被解决掉的BUG。
转载自:https://juejin.cn/post/7400582230802759720