有十万条数据,要渲染到页面上去,如何保证不卡主页面的情况下渲染数据?
核心观点:页面渲染要比 JS 执行慢得多
一般有两种做法:
- 时间分片(分片渲染)
- 虚拟列表
时间分片(分片渲染)
原理:不一次性在页面插入所有 DOM,而是只插入一部分(至少覆盖可视区域),等一段时间再插入一部分,以此类推直到插入所有 DOM
这样可以将一个长任务打散成一些短任务,保证渲染引擎及时渲染
等一段时间:
- 使用
requestAnimationFrame
保证回调函数在屏幕每一次的刷新间隔中被执行一次 - 而不是
setTimeout
,它无法保证
DOM 插入:
- 使用
DocumentFragment
避免频繁插入 DOM,以减少重排与重绘
虚拟列表
减少 DOM 数量,只有可视区域的 DOM,滚动时动态修改 DOM 的内容——“用有限的 DOM 来加载无限的数据”
定高虚拟列表
定高虚拟列表 实现的一个 item 高度固定且已知的 Demo,旨在理解其原理
不定高虚拟列表
不定高是指列表项高度不固定(如:根据内容撑开)
在虚拟列表中应用动态高度的解决方案一般有如下三种:
- 对组件属性
itemHeight
进行扩展,支持传递类型为数字、数组、函数- 可以是一个固定值,如 100,此时列表项是固高的
- 可以是一个包含所有列表项高度的数据,如
[50, 20, 100, 80, ...]
- 可以是一个根据列表项索引返回其高度的函数:
(index: number): number
这种方式虽然有比较好的灵活度,但仅适用于可以预先知道或可以通过计算得知列表项高度的情况,依然无法解决列表项高度由内容撑开的情况。
- 将列表项渲染到屏幕外,对其高度进行测量并缓存,然后再将其渲染至可视区域内。
由于预先渲染至屏幕外,再渲染至屏幕内,这导致渲染成本增加一倍。而且要将缓冲区增大,防止可视区域渲染不及时
- 以预估高度先行渲染,然后获取真实高度并缓存。
这种是比较常见的做法,Demo:不定高虚拟列表
瀑布流虚拟列表
Demo:瀑布流虚拟列表