1. 虚拟列表技术解析
第一次看到闲鱼网页版商品列表时,我惊讶地发现无论怎么滚动,DOM元素数量始终保持在20个左右。这与我认知中的传统分页加载完全不同——传统方式在滚动到第1000页时,浏览器内存中会堆积上千个DOM节点,最终导致页面卡顿甚至崩溃。
虚拟列表(Virtual List)技术的核心思想可以用一个生活中的例子来理解:想象你站在一栋100层高楼的电梯里,透过电梯的窗户(可视区域)你只能看到当前楼层附近的几层。虚拟列表就是这栋楼的"智能电梯",它只渲染你当前能看到的这几层(DOM节点),当你滚动(电梯移动)时,动态回收离开视野的楼层并渲染新进入视野的楼层。
1.1 核心实现原理
虚拟列表的实现依赖三个关键计算:
- 可视区域计算:
javascript复制// 可视区域能容纳的条目数 = 容器高度 / 单条高度 + 缓冲条目
visibleCount = Math.ceil(containerHeight / itemHeight) + bufferSize
- 滚动位置映射:
javascript复制// 当前滚动位置对应的起始索引
startIndex = Math.floor(scrollTop / itemHeight)
// 结束索引
endIndex = startIndex + visibleCount
- 动态渲染范围:
javascript复制// 只渲染可视区域内的数据
visibleData = totalData.slice(startIndex, endIndex)
关键细节:必须使用绝对定位+transform来实现位移,而非修改top/left值。因为transform不会触发重排(reflow),性能更好。
1.2 性能对比实测
我做了组对比测试,加载10000条数据:
| 方案 | 初始加载DOM数 | 滚动到末尾DOM数 | 内存占用 | FPS平均值 |
|---|---|---|---|---|
| 传统渲染 | 10000 | 10000 | 1.2GB | 12 |
| 虚拟列表 | 20 | 20 | 80MB | 58 |
| 虚拟列表+缓冲 | 25 | 25 | 85MB | 60 |
实测发现虚拟列表的内存占用只有传统方案的6%,而帧率保持接近60FPS的流畅水平。缓冲条目(bufferSize)设置为2-3时,能有效避免快速滚动时的白屏现象。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Vue3虚拟列表完整实现
2.1 基础结构搭建
先创建虚拟列表的HTML骨架:
html复制<div class="virtual-list" ref="listRef" @scroll="handleScroll">
