虚拟列表解析

0 阅读2分钟

虚拟列表

划分为三个区域 : 分别是上缓冲区(0/2个元素),可视区(n个元素),下缓冲区(2个元素)。

当我们滚动到一个元素离开可视区范围内时,就去掉上缓冲区顶上的一个元素,然后再下缓冲区增加一个元素。

(容器高度) 滚动条滚动 → 
​
•   得到 scrollTop 
​
•       → 通过 scrollTop 与元素的累计高度(itemN.to)计算 
​
•           →得到**起始索引**(startIndex) 
​
•               → 渲染对应元素 
​
•                   → 用 offset 调整渲染位置(对齐真实 top

其中所有虚拟列表的核心都在于计算: 起始索引 和 容器高度

起始索引 : 可视区从第几个元素开始显示 (优化点)

容器高度 : 整个内容区域的高度

依赖 滚动距离 (scrollTop) 和元素的累计高度(itemN.top)数据。

得出真正 内容容器偏移量(offset ) :视区第一个渲染元素的 真实 top 位置(只显示一部分),position: absolute + top,避免大量重排

性能保障: 必须使用 节流 (Throttle)requestAnimationFrame 来处理 scroll 事件,以限制计算频率,避免浏览器主线程卡顿,确保平滑滚动。

特殊情况

处理列表高度的两种情况 :

固定高度:就可以直接用过 元素个数 固定高度获得容器高度,然后 用当前key 固定高度 得到元素的累计高度,就得到起始索引

不固定高度:就不一样,无法固定计算元素的高度,就获取不到固定某个元素的累计高度就无法得到起始索引

通过动态计算元素的累计高度(top)确定起始索引,当用户滚动到某个元素,而这个元素还没缓存累积高度时:

  1. 从已知的最后一个元素开始累加高度
  2. 依次计算未知元素的 top 并缓存
  3. 一旦累加到 scrollTop 所对应的区间,就确定了 startIndex

可以结合缓存数组+二分查找快速定位 startIndex,避免从头线性累加。

优化核心都是:

  1. 减少节点的创建和销毁的开销: 这是虚拟列表的根本目的,通过仅渲染缓冲区+可视区实现。
  2. 对正在使用节点进行复用: 现代框架通常通过 VDOM Diff/Patch 机制,将离开上缓冲区的 DOM 节点复用到下缓冲区,减少实际的 DOM 创建/销毁操作。
  3. 提前创建好子元素并缓存起来: 这里的“缓存”主要指数据和计算结果的缓存(如高度缓存、定位点 top 缓存),而不是 DOM 节点的缓存。

参考:三种虚拟列表原理与实现在前端工作中免不了接触到虚拟列表,本文通过简单易懂的图和代码手把手教大家实现三种虚拟列表。看完本文 - 掘金