前言
很早之前面视的时候有被问道过,当时确实是没遇到过这个问题,因此是直接回复了不知道。虽然最后并没有对面视产生很大的影响,却也一直是心中的一块"病",时不时的会想起来
这不,最近又想起来这事,故打算探究一波
什么是长列表
长列表是指一次性返回n条数据交由前端渲染,如何做到页面不卡或性能最优
示例
使用mock模拟一万条数据返回并一次性渲染,会发现页面有长时间的空白展示,如果涉及的dom结构更为复杂,则该时间将进一步拉长。因此要想办法将这段"空窗期"填补上,先让用户"有事可做"
解决思路
为了避免用户误以为是程序缺陷,需要先将用户可视区域内的内容展示出来。大致有如下三种:
分页:每次加载一部分,逐渐累加
分片加载:先把首屏加载,剩下部分交浏览器空闲时继续累加
虚拟列表:使用js动态替换首屏内容,而不是加载更多
分片加载
createDocumentFragment创建的dom片段在假如body之前是存在于内存中的,故对其进行的dom操作并不会引起浏览器的重绘或者重排等操作,对于每一个li的内容可以使用该api生成好后再向dom中插入
requestAnimationFram能确保在每次刷新前被执行一次,相比setTimeout其避免了丢帧
利用这两个api,我们率先渲染可视区的n条数据,后续的渲染则在屏幕刷新时继续
虚拟列表
页面结构
我们需要给最外层的容器设置可视区的高度
为了模拟滚动条的高度变化,不能直接替换10条数据,故需要一个div标识全部数据的高度以撑开可视区容器
需要一个div来展示真正的十条数据
渲染静态可视区数据
使用slice不断的从总数据data中截取指定长度的数据来做到动态替换以保证页面中始终只有n条数据,为了达到这一目地,需要实时计算记录开始及结束位置,并单独使用数组作为可视区的待渲染容器,则初始值如下
支持滑动
在页面滑动过程中更新开始及结束位置并从data中截取对应的列表数据
修正缺陷
此时从控制台的页面结构中来看已经完成了虚拟列表的功能,但是页面的显示却是不对的:可视区被滚跑了
为此,需要利用translate3d做一次"回滚"处理:向上滚动是三个半,则可视区向下回滚三个半
此时,页面效果如下