标准答案
- 长列表卡顿通常来自 DOM 数量过多、行组件重、滚动中频繁计算或图片加载过多。
- 虚拟滚动只渲染可见区域和少量缓冲区,大幅减少 DOM 节点和 React 渲染成本。
- 固定高度列表实现更简单,动态高度列表需要测量、缓存高度并处理滚动位置修正。
- 行组件要保持 key 稳定,避免滚动时状态错位或大量重建。
- 服务端分页、无限滚动、图片懒加载和占位骨架可以和虚拟滚动一起使用。
题目解析
这道题要把列表数据规模、渲染规模和交互体验分开看。不是所有列表都需要虚拟滚动。
如果只有几十条数据,组件拆分和 memo 可能已经足够;几千条甚至更多时,虚拟滚动才更有价值。
虚拟滚动也有代价,例如可访问性、浏览器查找、动态高度、滚动定位和表格固定列都会变复杂。
代码示例
下面展示虚拟列表的核心思路:只根据可见范围渲染部分行。
TSX
function VirtualList({ items, start, end }: {
items: User[]
start: number
end: number
}) {
const visibleItems = items.slice(start, end)
return (
<div>
{visibleItems.map(item => (
<UserRow key={item.id} user={item} />
))}
</div>
)
}常见误区
- 列表数据量很小也上复杂虚拟滚动,增加维护成本。
- 用 index 作为动态列表 key,滚动、插入或排序后行状态错位。
- 没有处理动态高度和滚动定位,导致跳动、空白或定位不准。