虚拟列表
划分为三个区域 : 分别是上缓冲区(0/2个元素),可视区(n个元素),下缓冲区(2个元素)。
当我们滚动到一个元素离开可视区范围内时,就去掉上缓冲区顶上的一个元素,然后再下缓冲区增加一个元素。
(容器高度) 滚动条滚动 →
• 得到 scrollTop
• → 通过 scrollTop 与元素的累计高度(itemN.to)计算
• →得到**起始索引**(startIndex)
• → 渲染对应元素
• → 用 offset 调整渲染位置(对齐真实 top)
其中所有虚拟列表的核心都在于计算: 起始索引 和 容器高度
起始索引 : 可视区从第几个元素开始显示 (优化点)
容器高度 : 整个内容区域的高度
依赖 滚动距离 (scrollTop) 和元素的累计高度(itemN.top)数据。
得出真正 内容容器偏移量(offset ) :视区第一个渲染元素的 真实 top 位置(只显示一部分),position: absolute + top,避免大量重排
性能保障: 必须使用 节流 (Throttle) 或 requestAnimationFrame 来处理 scroll 事件,以限制计算频率,避免浏览器主线程卡顿,确保平滑滚动。
特殊情况
处理列表高度的两种情况 :
固定高度:就可以直接用过 元素个数 固定高度获得容器高度,然后 用当前key 固定高度 得到元素的累计高度,就得到起始索引
不固定高度:就不一样,无法固定计算元素的高度,就获取不到固定某个元素的累计高度就无法得到起始索引
通过动态计算元素的累计高度(top)确定起始索引,当用户滚动到某个元素,而这个元素还没缓存累积高度时:
- 从已知的最后一个元素开始累加高度
- 依次计算未知元素的 top 并缓存
- 一旦累加到 scrollTop 所对应的区间,就确定了 startIndex
可以结合缓存数组+二分查找快速定位 startIndex,避免从头线性累加。
优化核心都是:
- 减少节点的创建和销毁的开销: 这是虚拟列表的根本目的,通过仅渲染缓冲区+可视区实现。
- 对正在使用节点进行复用: 现代框架通常通过 VDOM Diff/Patch 机制,将离开上缓冲区的 DOM 节点复用到下缓冲区,减少实际的 DOM 创建/销毁操作。
- 提前创建好子元素并缓存起来: 这里的“缓存”主要指数据和计算结果的缓存(如高度缓存、定位点
top缓存),而不是 DOM 节点的缓存。
参考:三种虚拟列表原理与实现在前端工作中免不了接触到虚拟列表,本文通过简单易懂的图和代码手把手教大家实现三种虚拟列表。看完本文 - 掘金