虚拟滚动技术 --- 解决加载大量列表DOM导致页面卡顿

JavaScript04

虚拟滚动技术 --- 解决加载大量列表DOM导致页面卡顿,第1张

1、dom过多,占用过多的内存。

2、操纵dom时触发重排重绘,消耗浏览器性能。特别是每一次滚动事件将会让对应 DOM 中的所有元素重新渲染。

3、资源加载阻塞,比如js资源放在body之前、行内script阻塞、css加载会阻塞DOM树渲染(css并不会阻塞DOM树的解析)资源过大阻塞

至于第二个问题,详见 网红问题--前端性能优化(全流程) 或者 js回流和重绘

现在看来,这两点大条件是客观存在的,我们无法改变,所以这时候解决的方案就呼之欲出了,别让浏览器一次性渲染这么多元素,这里通常会对应三种做法来减少元素渲染。

这个方案是大家浏览到页面所常用的,通常在需要展示非常多行的数据时页面会采用分页的做法来分割数据,但在SQL结果集的场景下并不是通用方案,原因是虽然该方法减少了一次性所渲染的行数,但是如果查询的表列数非常多的话,还是有很大概率需要渲染非常多的元素,所以不是一个稳妥的选型。

该方案的解决方法是第一次只渲染所能承受范围内的数据量,当滚动条拖动接近底部(或右部)时,再去追加下一批所需要渲染的元素,该方案也是有一个明显的缺陷在于,无限地滚动下去必然会触及浏览器的性能瓶颈,而且所需要渲染的元素会越来越多,性能迟早会被拖垮。

其实答案已经隐藏在上面两种解决方案里面了,数据分页的方案是一次性渲染固定行数和列数的数据量,缺点是怕一次性的量就逼近上限。无限滚动的方案是想看更多数据的时候再继续渲染,不看就不渲染避免性能浪费,但缺点就在于只要一直触发“继续看”的操作,那么之前遗留的数据将会越来越多导致性能雪崩。

这时候可以把两个方案中和一下,既然在有限的视窗中我们只能看到一部分的数据,那么我们就通过计算可视范围内的单元格,这样就保证了每一次拖动,我们渲染的 DOM 元素始终是可控的,不会像数据分页方案怕一次性渲染过多,也不会发生无限滚动方案中的老数据堆积现象。接下来我们用一张图来表示虚拟滚动的表现形式。

根据图中我们可以看到,无论我们如何滚动,我们可视区域的大小其实是不变的,那么要做到性能最大化就需要尽量少地渲染 DOM 元素,而这个最小值也就是可视范围内需要展示的内容,也就是图中的绿色区块,在可视区域之外的元素均可以不做渲染。

可以通过如下几步来实现虚拟滚动:

​ 在项目中有一个sku表(是一个尺码和颜色乘积的表格),假如有10个颜色,20个尺码,那这个sku表就会有200行。有一个客户有100个颜色的需求,100个颜色的时候如果有5个尺码,就会有500行,这样会使页面很卡,于是找到了vue-virtual-scroll-list这个插件。

剩下的参数https://www.npmjs.com/package/vue-virtual-scroll-list

官网地址 https://tangbc.github.io/vue-virtual-scroll-list/#/

如上图,他只渲染keeps传入的个数,滚动时通过改变padding的值来模拟滚动,里面的每一个item在滚动时动态替换里面的值

核心源码如下

永远之渲染props的keeps传入的个数,所以这样不会卡