有十万条数据,要渲染到页面上去,如何保证不卡主页面的情况下渲染数据?

核心观点:页面渲染要比 JS 执行慢得多

一般有两种做法:

  1. 时间分片(分片渲染)
  2. 虚拟列表

时间分片(分片渲染)

原理:不一次性在页面插入所有 DOM,而是只插入一部分(至少覆盖可视区域),等一段时间再插入一部分,以此类推直到插入所有 DOM

这样可以将一个长任务打散成一些短任务,保证渲染引擎及时渲染

等一段时间:

  • 使用 requestAnimationFrame 保证回调函数在屏幕每一次的刷新间隔中被执行一次
  • 而不是 setTimeout,它无法保证

DOM 插入:

  • 使用 DocumentFragment 避免频繁插入 DOM,以减少重排与重绘

虚拟列表

减少 DOM 数量,只有可视区域的 DOM,滚动时动态修改 DOM 的内容——“用有限的 DOM 来加载无限的数据”

定高虚拟列表

定高虚拟列表 实现的一个 item 高度固定且已知的 Demo,旨在理解其原理

不定高虚拟列表

不定高是指列表项高度不固定(如:根据内容撑开)

在虚拟列表中应用动态高度的解决方案一般有如下三种:

  1. 对组件属性 itemHeight 进行扩展,支持传递类型为数字、数组、函数
    • 可以是一个固定值,如 100,此时列表项是固高的
    • 可以是一个包含所有列表项高度的数据,如 [50, 20, 100, 80, ...]
    • 可以是一个根据列表项索引返回其高度的函数:(index: number): number

这种方式虽然有比较好的灵活度,但仅适用于可以预先知道或可以通过计算得知列表项高度的情况,依然无法解决列表项高度由内容撑开的情况。

  1. 将列表项渲染到屏幕外,对其高度进行测量并缓存,然后再将其渲染至可视区域内。

由于预先渲染至屏幕外,再渲染至屏幕内,这导致渲染成本增加一倍。而且要将缓冲区增大,防止可视区域渲染不及时

  1. 预估高度先行渲染,然后获取真实高度并缓存。

这种是比较常见的做法,Demo:不定高虚拟列表

瀑布流虚拟列表

Demo:瀑布流虚拟列表