使用 TanStack Virtual 进行虚拟化

发布: (2026年2月18日 GMT+8 04:39)
7 分钟阅读
原文: Dev.to

Source: Dev.to

优化性能是 React 社区的常见话题。用户期望在处理可能增长到数千条记录的大型数据集时,能够实现流畅的滚动和快速的交互。

虚拟化通过仅渲染可见的元素(加上少量缓冲区),而不是一次性加载成千上万的 DOM 元素,从而提升大列表的性能。随着用户滚动,元素会动态地被添加和移除,同时列表仍保持完整渲染数据集的外观,且不会出现性能下降。

为什么虚拟化是必不可少的

在处理大量数据集时:

  • Memory consumption – 渲染大量 DOM 元素会占用相当多的内存。
  • Initial rendering speed – 当 React 构建并调和一个庞大的树时,初始显示会变慢。
  • Scrolling responsiveness – 处理大数据集会增加工作负载和 DOM 大小,导致滚动卡顿。
  • User experience – 由于滚动和点击时响应缓慢,应用可能会给人出现故障的感觉。

虚拟化显著减少了 DOM 节点数量,通常会带来更流畅的滚动和更快的交互。实现 React 虚拟化的方法有很多,在本文中,我们将重点关注 TanStack Virtual

Introduction to TanStack Virtual

TanStack Virtual 是一个 headless 虚拟化库。它 包含预构建的 UI 组件。相反,它提供虚拟化 engine(ranges、offsets、total size 和 measurement utilities),让您能够完全控制标记、样式、布局和交互。当您的列表项不仅是基本行,而是徽章、菜单、图片、按钮以及复杂设计等精细 UI 元素时,这一点尤为重要。

安装

npm install @tanstack/react-virtual
# or
yarn add @tanstack/react-virtual
# or
pnpm add @tanstack/react-virtual

Understanding TanStack Virtual Fundamentals

TanStack Virtual 并不是一个可以直接放入应用后就不管的 UI 组件库。它是一个轻量级工具,负责处理虚拟化的难点,确定:

  • 哪些项目应该可见,
  • 这些项目在滚动空间中应放置在哪里,
  • 以及完整列表应呈现多大的尺寸(从而使滚动条自然工作)。

其余的 UI 仍需你自行构建:标记、样式、布局和交互。

现在,让我们一步一步分析它。

Source:

心智模型(“幻象”)

虚拟列表通常包含三个部分:

  1. 滚动容器 – 一个具有固定高度并设置 overflow: autodiv
  2. 占位元素 – 一个内部元素,其高度等于列表的总高度(getTotalSize())。
  3. 虚拟项 – 仅渲染可见的项目,使用 transform: translateY(...) 定位。

示例

import { useVirtualizer } from "@tanstack/react-virtual";

export function BasicVirtualList() {
  const parentRef = React.useRef(null);

  const items = React.useMemo(
    () => Array.from({ length: 100_000 }, (_, i) => `Item ${i + 1}`),
    []
  );

  const virtualizer = useVirtualizer({
    count: items.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 44, // fixed row height
    overscan: 8,
  });

  return (
    <div ref={parentRef} style={{ height: "400px", overflow: "auto" }}>
      <div style={{ height: virtualizer.getTotalSize() }}>
        {virtualizer.getVirtualItems().map((vItem) => (
          <div
            key={vItem.key}
            style={{
              position: "absolute",
              top: 0,
              left: 0,
              width: "100%",
              height: `${vItem.size}px`,
              transform: `translateY(${vItem.start}px)`,
            }}
          >
            {items[vItem.index]}
          </div>
        ))}
      </div>
    </div>
  );
}

您在每次实现中都会使用的关键概念

  • estimateSize – 返回估计的项目高度(或水平列表的宽度)的函数。
  • getItemKey – 当列表可能因排序、过滤或新数据而变化时,使用一致的键,以确保虚拟化保持稳定。
  • overscan – 控制在视口上方和下方额外渲染的项目数量。更高的 overscan 可以在快速滚动时减少空白间隙,但会增加每次滚动的工作量。

除了配置之外,实际因素也会影响虚拟化在您的应用中的有效性。

Tips for Virtualisation

  • 固定 vs. 可变项目高度 – 固定布局更简单;可变高度需要仔细测量和管理尺寸。
  • 行状态 – 虚拟化的行在滚动时可能会挂载和卸载。确保关键数据或状态不要仅存放在行组件内部。
  • 焦点与可访问性 – 当行被卸载时,如果焦点消失,输入和键盘导航可能会中断。
  • 图片和动态内容 – 加载缓慢的媒体可能会改变高度,如果处理不当会导致滚动跳动。
  • 性能验证 – 使用 React Profiler 和 Chrome Performance 工具比较前后结果。

常见陷阱(以及…)

此部分的内容可稍后添加。

如何避免它们

  • 快速滚动时出现空白间隙
    稍微增加 overscan,以便在可视视口之外渲染更多项目。

  • 可变内容导致的滚动跳动
    通过设置固定高度或宽高比为图像预留空间,或启用精确测量,以防止动态高度变化导致的滚动位置偏移。

  • 行状态丢失
    将状态提升并按 id 存储。避免仅在行组件内部保存关键状态,因为它们在滚动时可能会挂载和卸载。

  • 键错误
    当列表顺序可能变化时,使用 getItemKey 提供稳定的键。不要依赖数组索引。

总结

虚拟化是您在 React 中对大型列表进行性能提升的最有效方法之一。使用 TanStack React Virtual,您将获得一个多功能、无 UI 框架的引擎,能够平稳地集成到实际应用中——尤其是在您需要对 UI 布局进行完整控制时。

0 浏览
Back to Blog

相关文章

阅读更多 »