标准答案

  1. 长列表卡顿通常来自 DOM 数量过多、行组件重、滚动中频繁计算或图片加载过多。
  2. 虚拟滚动只渲染可见区域和少量缓冲区,大幅减少 DOM 节点和 React 渲染成本。
  3. 固定高度列表实现更简单,动态高度列表需要测量、缓存高度并处理滚动位置修正。
  4. 行组件要保持 key 稳定,避免滚动时状态错位或大量重建。
  5. 服务端分页、无限滚动、图片懒加载和占位骨架可以和虚拟滚动一起使用。

题目解析

这道题要把列表数据规模、渲染规模和交互体验分开看。不是所有列表都需要虚拟滚动。

如果只有几十条数据,组件拆分和 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,滚动、插入或排序后行状态错位。
  • 没有处理动态高度和滚动定位,导致跳动、空白或定位不准。

作者信息