背景
一个滚动列表,无论是pc端还是移动端,一旦列表内容过长,上千甚至上万,对浏览器的性能肯定是会有影响的。这个影响的根本大部分是在渲染,因为重排相对于重绘更消耗性能。甚至页面初始化后,会显示很长时间的loading,这种体验是很差的。
那有没有办法优化这个问题呢?这个就是这次的主题,无限滚动列表。
实现的方式有很多,有好有坏,由于刚开始没有参考资料,自己写了一版。
大致原理是,计算当前视口的高度,获取滚动的每一项的高度,用视口高度/每一项的高度,就得到了当前可以容纳的最大项。默认进入页面的时候,第一项肯定是0,然后加上最大项,这就是我们真正需要渲染的数量。然后我们需要给当前所有列表的容器加上一个动态高度,这样才能撑起滚动的元素。
容器里面的元素给绝对定位,然后通过translateY将决定定位的元素恢复到正确的位置上,当我们滚动的时候,使用 (当前item的索引 + startindex - buffer) * itemHeight 来获取正确translateY
这样,就算你有一亿条数据,也仅仅渲染这几条,当然不会卡顿。
但是正如上图所示,如果这时候你向下滚动,由于只渲染了这几条,所以当你滚动的时候下面是什么都没有,是一片白的。那么如何解决这个问题呢?
我们需要根据滚动距离动态更新第一项的索引,初始化的时候是0,如果每一项高度是20,那么滚动到21的时候,第一项的索引就编程了1,整体都往后移动了一个,这样列表就增量更新了当前视口的列表,但是渲染的数量还是之前那么多。
这样就完成了最基本的无限滚动列表,不过,如果滚动稍微快一点的话,还是有空白,因为增量更新的还没来得及渲染完毕,所以这个时候我们需要前后都加上buffer列表项,以适应这种情况。
当滚动开始的时候就会提前渲染增量部分。
不过,当你滚动更快的时候,还是会有空白的部分,所以需要实现自定义scroll行为,控制用户滚动速度,即可。