countgetScrollElementestimateSizeenableddebuginitialRectonChangeoverscanhorizontalpaddingStartpaddingEndscrollPaddingStartscrollPaddingEndinitialOffsetgetItemKeyrangeExtractorscrollToFnobserveElementRectobserveElementOffsetmeasureElementscrollMargingaplanesisScrollingResetDelayuseScrollendEventisRtluseAnimationFrameWithResizeObserveroptionsscrollElementgetVirtualItemsgetVirtualIndexesscrollToOffsetscrollToIndexgetTotalSizemeasuremeasureElementresizeItemscrollRectshouldAdjustScrollPositionOnItemSizeChangeisScrollingscrollDirectionscrollOffsetThe Virtualizer 类是 TanStack Virtual 的核心。Virtualizer 实例通常由您的框架适配器为您创建,但您会直接接收到 virtualizer。
export class Virtualizer<TScrollElement = unknown, TItemElement = unknown> {
constructor(options: VirtualizerOptions<TScrollElement, TItemElement>)
}
export class Virtualizer<TScrollElement = unknown, TItemElement = unknown> {
constructor(options: VirtualizerOptions<TScrollElement, TItemElement>)
}
count: number
count: number
要虚拟化的项目总数。
getScrollElement: () => TScrollElement
getScrollElement: () => TScrollElement
一个返回 virtualizer 可滚动元素的函数。如果元素尚未可用,则可能返回 null。
estimateSize: (index: number) => number
estimateSize: (index: number) => number
🧠 如果您正在动态测量元素,建议估算项目可能的最大尺寸(宽度/高度,在舒适范围内)。这将确保像平滑滚动这样的功能有更好的机会正常工作。
此函数会接收每个项目的索引,并应返回每个项目的实际尺寸(如果您将使用 virtualItem.measureElement 动态测量项目,则为估算尺寸)。此测量应根据 virtualizer 的方向返回宽度或高度。
enabled?: boolean
enabled?: boolean
设置为 false 以禁用 scrollElement 观察器并重置 virtualizer 的状态
debug?: boolean
debug?: boolean
设置为 true 以启用调试日志
initialRect?: Rect
initialRect?: Rect
scrollElement 的初始 Rect。这在您需要在 SSR 环境中运行 virtualizer 时非常有用,否则 initialRect 将在挂载时由 observeElementRect 实现计算。
onChange?: (instance: Virtualizer<TScrollElement, TItemElement>, sync: boolean) => void
onChange?: (instance: Virtualizer<TScrollElement, TItemElement>, sync: boolean) => void
当 virtualizer 的内部状态发生变化时触发的回调函数。它会接收 virtualizer 实例和 sync 参数。
sync 参数指示滚动当前是否正在进行。当滚动正在进行时为 true,当滚动停止或正在执行其他操作(如调整大小)时为 false。
overscan?: number
overscan?: number
在可见区域之上和之下要渲染的项目数量。增加此数字将增加渲染 virtualizer 所需的时间,但可能会减少滚动时在 virtualizer 顶部和底部看到缓慢渲染的空白项目的可能性。默认值为 1。
horizontal?: boolean
horizontal?: boolean
如果您的 virtualizer 是横向方向的,请将其设置为 true。
paddingStart?: number
paddingStart?: number
应用于 virtualizer 起始处的内边距(以像素为单位)。
paddingEnd?: number
paddingEnd?: number
应用于 virtualizer 结束处的内边距(以像素为单位)。
scrollPaddingStart?: number
scrollPaddingStart?: number
滚动到元素时应用于 virtualizer 起始处的内边距(以像素为单位)。
scrollPaddingEnd?: number
scrollPaddingEnd?: number
滚动到元素时应用于 virtualizer 结束处的内边距(以像素为单位)。
initialOffset?: number | (() => number)
initialOffset?: number | (() => number)
列表在渲染时滚动的到的位置。如果您在 SSR 环境中渲染 virtualizer 或条件性渲染 virtualizer,则此选项非常有用。
getItemKey?: (index: number) => Key
getItemKey?: (index: number) => Key
此函数会接收每个项目的索引,并应为该项目返回一个唯一的 key。此函数的默认功能是返回项目的索引,但您应该在可能的情况下覆盖它以返回整个集合中每个项目的唯一标识符。此函数应被 memoized 以防止不必要的重新渲染。
rangeExtractor?: (range: Range) => number[]
rangeExtractor?: (range: Range) => number[]
此函数接收可见范围索引,并应返回要渲染的索引数组。当您需要手动向 virtualizer 添加或删除项目时,即使不考虑可见范围,这也会很有用,例如渲染固定项目、标题、页脚等。默认范围提取器实现将返回可见范围索引,并导出为 defaultRangeExtractor。
scrollToFn?: (
offset: number,
options: { adjustments?: number; behavior?: 'auto' | 'smooth' },
instance: Virtualizer<TScrollElement, TItemElement>,
) => void
scrollToFn?: (
offset: number,
options: { adjustments?: number; behavior?: 'auto' | 'smooth' },
instance: Virtualizer<TScrollElement, TItemElement>,
) => void
一个可选函数,如果提供,应实现您的 scrollElement 的滚动行为。它将使用以下参数调用
请注意,内置的滚动实现作为 elementScroll 和 windowScroll 导出,它们会自动由框架适配器函数(如 useVirtualizer 或 useWindowVirtualizer)配置。
⚠️ 尝试将 smoothScroll 与动态测量元素一起使用将无效。
observeElementRect: (
instance: Virtualizer<TScrollElement, TItemElement>,
cb: (rect: Rect) => void,
) => void | (() => void)
observeElementRect: (
instance: Virtualizer<TScrollElement, TItemElement>,
cb: (rect: Rect) => void,
) => void | (() => void)
一个可选函数,如果提供,将在 scrollElement 更改时调用,并应实现 scrollElement 的 Rect(一个带有 width 和 height 的对象)的初始测量和连续监控。它会使用实例(该实例还允许您通过 instance.scrollElement 访问 scrollElement。内置实现作为 observeElementRect 和 observeWindowRect 导出,它们会自动由您的框架适配器导出的函数(如 useVirtualizer 或 useWindowVirtualizer)为您配置。
observeElementOffset: (
instance: Virtualizer<TScrollElement, TItemElement>,
cb: (offset: number) => void,
) => void | (() => void)
observeElementOffset: (
instance: Virtualizer<TScrollElement, TItemElement>,
cb: (offset: number) => void,
) => void | (() => void)
一个可选函数,如果提供,将在 scrollElement 更改时调用,并应实现 scrollElement 的滚动偏移量(一个数字)的初始测量和连续监控。它会使用实例(该实例还允许您通过 instance.scrollElement 访问 scrollElement。内置实现作为 observeElementOffset 和 observeWindowOffset 导出,它们会自动由您的框架适配器导出的函数(如 useVirtualizer 或 useWindowVirtualizer)为您配置。
measureElement?: (
element: TItemElement,
entry: ResizeObserverEntry | undefined,
instance: Virtualizer<TScrollElement, TItemElement>,
) => number
measureElement?: (
element: TItemElement,
entry: ResizeObserverEntry | undefined,
instance: Virtualizer<TScrollElement, TItemElement>,
) => number
当 virtualizer 需要动态测量项目的大小(宽度或高度)时,会调用此可选函数。
🧠 您可以使用 instance.options.horizontal 来确定是测量项目的宽度还是高度。
scrollMargin?: number
scrollMargin?: number
通过此选项,您可以指定滚动偏移量的来源。通常,此值代表滚动元素开始处与列表起始处之间的空间。这在常见场景中特别有用,例如当您在窗口 virtualizer 前有一个标题或当单个滚动元素内使用多个 virtualizer 时。如果您使用的是元素的绝对定位,您应该在 CSS transform 中考虑 scrollMargin。
transform: `translateY(${
virtualRow.start - rowVirtualizer.options.scrollMargin
}px)`
transform: `translateY(${
virtualRow.start - rowVirtualizer.options.scrollMargin
}px)`
要动态测量 scrollMargin 的值,您可以使用 getBoundingClientRect() 或 ResizeObserver。这在虚拟列表上方的项目可能会更改其高度的场景中很有用。
gap?: number
gap?: number
此选项允许您设置虚拟化列表中项目之间的间距。这对于在不手动调整每个项目的 margin 或 padding 的情况下保持项目之间一致的视觉分隔非常有用。该值以像素为单位指定。
lanes: number
lanes: number
列表被划分为的通道数(垂直列表的列,水平列表的行)。
isScrollingResetDelay: number
isScrollingResetDelay: number
此选项允许您指定在最后一个滚动事件之后等待多长时间以重置 isScrolling 实例属性。默认值为 150 毫秒。
此选项的实现是由跨不同浏览器可靠处理滚动行为的机制驱动的。直到所有浏览器都统一支持 scrollEnd 事件。
useScrollendEvent: boolean
useScrollendEvent: boolean
确定是否使用原生 scrollend 事件来检测滚动何时停止。如果设置为 false,则使用去抖动的后备机制在 isScrollingResetDelay 毫秒后重置 isScrolling 实例属性。默认值为 false。
此选项的实现是由跨不同浏览器可靠处理滚动行为的机制驱动的。直到所有浏览器都统一支持 scrollEnd 事件。
isRtl: boolean
isRtl: boolean
是否反转水平滚动以支持从右到左的语言区域。
useAnimationFrameWithResizeObserver: boolean
useAnimationFrameWithResizeObserver: boolean
此选项启用将 ResizeObserver 测量包装在 requestAnimationFrame 中,以实现更流畅的更新并减少布局抖动。默认值为 false。
它通过确保测量与渲染周期对齐,有助于防止“ResizeObserver loop completed with undelivered notifications”错误。这可以提高性能并减少 UI 抖动,尤其是在动态调整元素大小时。但是,由于 ResizeObserver 已经异步运行,添加 requestAnimationFrame 可能会引入轻微的测量延迟,这在某些情况下可能很明显。如果调整大小操作开销很小且不会导致回流,则启用此选项可能不会带来显著的好处。
以下属性和方法可在 virtualizer 实例上使用
options: readonly Required<VirtualizerOptions<TScrollElement, TItemElement>>
options: readonly Required<VirtualizerOptions<TScrollElement, TItemElement>>
virtualizer 的当前选项。此属性通过您的框架适配器更新,并且是只读的。
scrollElement: readonly TScrollElement | null
scrollElement: readonly TScrollElement | null
virtualizer 的当前 scrollElement。此属性通过您的框架适配器更新,并且是只读的。
type getVirtualItems = () => VirtualItem[]
type getVirtualItems = () => VirtualItem[]
返回 virtualizer 当前状态的虚拟项目。
type getVirtualIndexes = () => number[]
type getVirtualIndexes = () => number[]
返回 virtualizer 当前状态的虚拟行索引。
scrollToOffset: (
toOffset: number,
options?: {
align?: 'start' | 'center' | 'end' | 'auto',
behavior?: 'auto' | 'smooth'
}
) => void
scrollToOffset: (
toOffset: number,
options?: {
align?: 'start' | 'center' | 'end' | 'auto',
behavior?: 'auto' | 'smooth'
}
) => void
将 virtualizer 滚动到提供的像素偏移量。您可以选择传递一个对齐模式以将滚动锚定到 scrollElement 的特定部分。
scrollToIndex: (
index: number,
options?: {
align?: 'start' | 'center' | 'end' | 'auto',
behavior?: 'auto' | 'smooth'
}
) => void
scrollToIndex: (
index: number,
options?: {
align?: 'start' | 'center' | 'end' | 'auto',
behavior?: 'auto' | 'smooth'
}
) => void
将 virtualizer 滚动到提供的索引的项目。您可以选择传递一个对齐模式以将滚动锚定到 scrollElement 的特定部分。
getTotalSize: () => number
getTotalSize: () => number
返回虚拟化项目的总像素大小。如果您选择在渲染时动态测量元素,此测量值将逐渐变化。
measure: () => void
measure: () => void
重置任何之前的项目测量。
measureElement: (el: TItemElement | null) => void
measureElement: (el: TItemElement | null) => void
使用您配置的 measureElement virtualizer 选项测量元素。您负责在 virtualizer 标记中调用此函数(例如,使用 React 的 ref 回调 prop),同时添加 data-index。
<div
key={virtualRow.key}
data-index={virtualRow.index}
ref={virtualizer.measureElement}
style={...}
>...</div>
<div
key={virtualRow.key}
data-index={virtualRow.index}
ref={virtualizer.measureElement}
style={...}
>...</div>
默认情况下,measureElement virtualizer 选项配置为使用 getBoundingClientRect() 测量元素。
resizeItem: (index: number, size: number) => void
resizeItem: (index: number, size: number) => void
手动更改虚拟化项目的大小。使用此函数手动设置此索引的计算大小。在使用某些自定义变形过渡时很有用,并且您事先知道变形后项目的大小。
您也可以使用此方法与节流的 ResizeObserver 结合使用,而不是 Virtualizer.measureElement,以减少重新渲染。
⚠️ 请注意,当使用 Virtualizer.measureElement 监视某个项目时手动更改该项目的大小,将导致不可预测的行为,因为 Virtualizer.measureElement 也在改变大小。但是,您可以在同一个 virtualizer 实例中使用 resizeItem 或 measureElement,但应用于不同的项目索引。
scrollRect: Rect
scrollRect: Rect
scroll 元素的当前 Rect。
shouldAdjustScrollPositionOnItemSizeChange: undefined | ((item: VirtualItem, delta: number, instance: Virtualizer<TScrollElement, TItemElement>) => boolean)
shouldAdjustScrollPositionOnItemSizeChange: undefined | ((item: VirtualItem, delta: number, instance: Virtualizer<TScrollElement, TItemElement>) => boolean)
shouldAdjustScrollPositionOnItemSizeChange 方法可以精细地控制在动态渲染的项目大小与估算大小不同时调整滚动位置。当跳转到列表的中间并向后滚动时,新元素的大小可能与最初估算的大小不同。这种差异可能导致后续项目移动,从而可能扰乱用户的滚动体验,尤其是在向后导航列表时。
isScrolling: boolean
isScrolling: boolean
布尔标志,指示列表当前是否正在滚动。
scrollDirection: 'forward' | 'backward' | null
scrollDirection: 'forward' | 'backward' | null
此选项指示滚动的方向,可能的值为“forward”(向前滚动,即向下滚动)和“backward”(向后滚动,即向上滚动)。当没有主动滚动时,该值为 null。
scrollOffset: number
scrollOffset: number
此选项表示沿滚动轴的当前滚动位置。它以像素为单位,从可滚动区域的起始点开始测量。
您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。