关于 tanstack-virtual
tanstack-virtual 是用于虚拟化大型列表、网格和表格的无头 UI 工具,面向需要呈现大量数据的前端开发者。它只渲染视口内的项目,并提供多种框架适配器。
主要功能
- 01仅渲染视口中的项目
- 02支持列表、网格和表格虚拟化
- 03支持动态尺寸测量
- 04支持滚动到指定项目或位置
- 05提供多框架适配器
适用场景
- 01渲染包含数千行的数据列表
- 02构建虚拟化表格
- 03实现无限滚动界面
- 04降低大型数据集的 DOM 节点数
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ oakoss/ agent-skills --skill tanstack-virtual安装后在 Claude Code 中输入/tanstack-virtual确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/dynamic-sizing.mdgrid-virtualization.mdinfinite-scroll.mdlist-virtualization.md详细介绍
TanStack Virtual
概述
TanStack Virtual 是一款无头 UI 工具,可对大型列表、网格和表格进行虚拟化。它只渲染视口中可见的项目,大幅减少 DOM 节点并提升包含数千行的数据集的性能。它提供适用于 React、Vue、Solid、Svelte、Lit 和 Angular 的框架适配器。
适用场景: 渲染数千行或数千列、构建虚拟化表格、实现无限滚动,以及展示 DOM 节点数量会影响性能的大型数据集。
不适用场景: 少于约 100 个项目的小型列表(不会带来性能提升)、服务端渲染的静态内容、出于 SEO 或无障碍访问要求而必须将所有项目放入 DOM 的布局,以及简单分页(此时应一次只渲染一页)。
快速参考
| 模式 | API | 要点 |
|---|---|---|
| 垂直列表 | useVirtualizer({ count, getScrollElement, estimateSize }) | 将项目包裹在绝对定位的容器中 |
| 水平列表 | useVirtualizer({ horizontal: true, ... }) | 使用 getTotalSize() 设置宽度,而非高度 |
| 网格布局 | 行虚拟器 + 列虚拟器 | 两个虚拟器实例共用一个滚动元素 |
| 动态尺寸 | ref={virtualizer.measureElement} | 为每个元素设置 data-index |
| 窗口滚动器 | useWindowVirtualizer({ count, estimateSize }) | 无需 getScrollElement |
| 滚动到指定项目 | virtualizer.scrollToIndex(index) | 支持 align: 'start' | 'center' | 'end' | 'auto' |
| 滚动到指定偏移 | virtualizer.scrollToOffset(px) | 支持 align 和 behavior: 'smooth' |
| 自定义键 | getItemKey: (index) => items[index].id | 稳定的键可改善测量缓存 |
| 预渲染范围 | overscan: 5 | 渲染视口外的额外项目(默认值:1) |
| 项目间距 | gap: 8 | 虚拟化项目之间的像素间距 |
| 多轨布局 | lanes: 3 | 瀑布流式列布局 |
| 内边距 | paddingStart: 100, paddingEnd: 100 | 首个项目前和最后一个项目后的空间 |
| RTL 支持 | isRtl: true | 从右向左的水平滚动 |
| 范围提取器 | rangeExtractor: (range) => [...] | 自定义渲染的索引(粘性页眉、页脚) |
| 禁用虚拟器 | enabled: false | 不渲染任何内容,并重置内部状态 |
| 强制重新测量 | virtualizer.measure() | 外部布局发生变化后调用 |
常见错误
| 错误 | 正确模式 |
|---|---|
滚动容器缺少 overflow: auto | 父元素必须设置 overflow: auto,并指定固定高度和宽度 |
使用 virtualItem.index 作为 React 键 | 使用 virtualItem.key,它会处理动态重排序 |
忘记在内部容器上设置 position: relative | 总尺寸容器必须设置为 position: relative |
使用 measureElement 时未设置 data-index | 动态测量要求在每个元素上设置 data-index={virtualItem.index} |
为动态项目设置的 estimateSize 过小 | 适当高估以防止滚动跳动;使用预期的最大尺寸 |
每次渲染时都重新创建 getScrollElement | 使用 ref 回调:() => parentRef.current |
未使用 getTotalSize() 设置容器尺寸 | 内部容器的高度或宽度必须等于 virtualizer.getTotalSize() |
使用绝对定位但未设置 transform | 使用 transform: translateY(item.start) 实现由 GPU 加速的定位 |
未设置固定尺寸却使用 contain: strict | contain: strict 要求滚动容器明确设置宽度和高度 |
| 使用 React Compiler 时未选择退出 | 在使用 useVirtualizer 的组件中添加 'use no memo' 指令 — 内部可变性会破坏记忆化 |
委派
如果有
tanstack-tableskill,请将数据表虚拟化委派给它。TanStack Table 内置了虚拟化集成。 否则,建议:npx skills add oakoss/agent-skills --skill tanstack-table如果有
tanstack-queryskill,请将数据获取和无限查询模式委派给它。 否则,建议:npx skills add oakoss/agent-skills --skill tanstack-query
参考资料
评论
支持 Markdown