虚拟列表是为了解决什么问题
真实项目中的痛点:
**想象一个后台系统:**用户列表:10 万条;订单列表:20 万条;日志列表:百万级;表格里还有:多列、复杂 DOM、hover、操作按钮、状态标签
直接 map 渲染:
data.map(item => <Row key={item.id} />)
**会遇到:**首次渲染卡死、滚动严重掉帧、内存暴涨和浏览器直接崩
**根因只有一个:**DOM 太多,浏览器不是怕 JS,浏览器最怕的是成千上万个 DOM 节点
总的来说虚拟列表就是只渲染可视区域内的列表项,而其余的用占位高度'假装存在'
虚拟列表的核心思想
我总结主要要理解这四点:
**1. 可视区域(viewport):**屏幕当前能看到的那一段高度
**2. 列表总高度(total height):**假设所有 item 都渲染后的总高度(假的,但要算出来)
**3. 起始索引和结束索引:**根据滚动距离,计算现在应该显示哪几条
**4. 偏移量(offset / translateY):**让当前渲染的 items 看起来在正确的位置
虚拟列表的本质实现原理
假设每一项高度固定,这个是最简单的,真是项目中大量列表数据一般都是每一项数据都是高度固定的
itemHeight = 50px
容器高度 = 500px
那屏幕最多能显示:500 / 50 = 10 条
通常会多渲染几条(缓冲区):实际渲染 = 10 + 4 = 14 条
根据滚动距离算索引
startIndex = Math.floor(scrollTop / itemHeight)
endIndex = startIndex + visibleCount
不渲染所有 DOM,但要让滚动条是对的
<div>
<div></div> <!-- 撑开高度 -->
<div></div> <!-- 只放可见项 -->
</div>
.phantom { height: totalCount * itemHeight; }

