Virtualizer

The Virtualizer 类是 TanStack Virtual 的核心。Virtualizer 实例通常由您的框架适配器为您创建,但您会直接接收到 virtualizer。

tsx
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

tsx
count: number
count: number

要虚拟化的项目总数。

getScrollElement

tsx
getScrollElement: () => TScrollElement
getScrollElement: () => TScrollElement

一个返回 virtualizer 的可滚动元素的方法。如果元素尚不可用,则可能返回 null。

estimateSize

tsx
estimateSize: (index: number) => number
estimateSize: (index: number) => number

🧠 如果您正在动态测量元素,建议您预估项目可能的最大尺寸(宽度/高度,在舒适范围内)。这将确保平滑滚动等功能更有可能正常工作。

此函数会传递每个项目的索引,并且应该返回每个项目的实际尺寸(如果您将使用 virtualItem.measureElement 动态测量项目,则返回预估尺寸)。此测量应返回宽度或高度,具体取决于您的 virtualizer 的方向。

可选选项

enabled

tsx
enabled?: boolean
enabled?: boolean

设置为 false 以禁用 scrollElement 观察器并重置 virtualizer 的状态

debug

tsx
debug?: boolean
debug?: boolean

设置为 true 以启用调试日志

initialRect

tsx
initialRect?: Rect
initialRect?: Rect

scrollElement 的初始 Rect。如果您需要在 SSR 环境中运行 virtualizer,这将非常有用,否则 initialRect 将在挂载时由 observeElementRect 实现计算。

onChange

tsx
onChange?: (instance: Virtualizer<TScrollElement, TItemElement>, sync: boolean) => void
onChange?: (instance: Virtualizer<TScrollElement, TItemElement>, sync: boolean) => void

一个回调函数,当 virtualizer 的内部状态更改时触发。它会传递 virtualizer 实例和 sync 参数。

sync 参数指示当前是否正在进行滚动。滚动正在进行时为 true,滚动停止或正在执行其他操作(例如调整大小)时为 false

overscan

tsx
overscan?: number
overscan?: number

要在可见区域上方和下方渲染的项目数。增加此数字将增加渲染 virtualizer 所需的时间,但可能会降低滚动时在 virtualizer 顶部和底部看到渲染缓慢的空白项目的可能性。

horizontal

tsx
horizontal?: boolean
horizontal?: boolean

如果您的 virtualizer 是水平方向的,请将其设置为 true

paddingStart

tsx
paddingStart?: number
paddingStart?: number

要应用于 virtualizer 开始处的内边距,以像素为单位。

paddingEnd

tsx
paddingEnd?: number
paddingEnd?: number

要应用于 virtualizer 结束处的内边距,以像素为单位。

scrollPaddingStart

tsx
scrollPaddingStart?: number
scrollPaddingStart?: number

当滚动到元素时,要应用于 virtualizer 开始处的内边距,以像素为单位。

scrollPaddingEnd

tsx
scrollPaddingEnd?: number
scrollPaddingEnd?: number

当滚动到元素时,要应用于 virtualizer 结束处的内边距,以像素为单位。

initialOffset

tsx
initialOffset?: number | (() => number)
initialOffset?: number | (() => number)

要应用于 virtualizer 的初始偏移量。这通常仅在您在 SSR 环境中渲染 virtualizer 时有用。

getItemKey

tsx
getItemKey?: (index: number) => Key
getItemKey?: (index: number) => Key

此函数会传递每个项目的索引,并且应该返回该项目的唯一键。此函数的默认功能是返回项目的索引,但您应该尽可能覆盖它,以返回整个集合中每个项目的唯一标识符。此函数应进行 memoized 以防止不必要的重新渲染。

rangeExtractor

tsx
rangeExtractor?: (range: Range) => number[]
rangeExtractor?: (range: Range) => number[]

此函数接收可见范围索引,并且应该返回要渲染的索引数组。如果您需要手动从 virtualizer 添加或删除项目,而无需考虑可见范围,例如渲染粘性项目、页眉、页脚等,这将非常有用。默认的 range extractor 实现将返回可见范围索引,并导出为 defaultRangeExtractor

scrollToFn

tsx
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 实现滚动行为。它将使用以下参数调用

  • 要滚动到的偏移量(以像素为单位)。
  • 一个对象,指示预估尺寸和实际尺寸之间是否存在差异 (adjustments) 和/或是否使用平滑动画调用了滚动 (behaviour)。
  • virtualizer 实例本身。

请注意,内置的滚动实现导出为 elementScrollwindowScroll,它们由框架适配器函数(如 useVirtualizeruseWindowVirtualizer)自动配置。

⚠️ 尝试将 smoothScroll 与动态测量的元素一起使用将不起作用。

observeElementRect

tsx
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(具有 widthheight 的对象)的初始测量和持续监控。它使用实例调用(实例还允许您通过 instance.scrollElement 访问 scrollElement)。内置实现导出为 observeElementRectobserveWindowRect,它们由您的框架适配器的导出函数(如 useVirtualizeruseWindowVirtualizer)自动为您配置。

observeElementOffset

tsx
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)。内置实现导出为 observeElementOffsetobserveWindowOffset,它们由您的框架适配器的导出函数(如 useVirtualizeruseWindowVirtualizer)自动为您配置。

measureElement

tsx
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

tsx
scrollMargin?: number
scrollMargin?: number

使用此选项,您可以指定滚动偏移量的原点。通常,此值表示滚动元素的开头和列表的开头之间的空间。这在常见场景中尤其有用,例如当您在窗口 virtualizer 之前有一个页眉,或者在单个滚动元素中使用多个 virtualizer 时。如果您正在使用元素的绝对定位,则应在 CSS 转换中考虑 scrollMargin

tsx
transform: `translateY(${
   virtualRow.start - rowVirtualizer.options.scrollMargin
}px)` 
transform: `translateY(${
   virtualRow.start - rowVirtualizer.options.scrollMargin
}px)` 

要动态测量 scrollMargin 的值,您可以使用 getBoundingClientRect() 或 ResizeObserver。当虚拟列表上方的项目可能更改其高度时,这很有帮助。

gap

tsx
gap?: number
gap?: number

此选项允许您设置虚拟化列表中项目之间的间距。这对于在项目之间保持一致的视觉分隔非常有用,而无需手动调整每个项目的边距或内边距。该值以像素为单位指定。

lanes

tsx
lanes: number
lanes: number

列表被划分为的通道数(对于垂直列表,也称为列;对于水平列表,也称为行)。

isScrollingResetDelay

tsx
isScrollingResetDelay: number
isScrollingResetDelay: number

此选项允许您指定在上次滚动事件后等待的时间,然后重置 isScrolling 实例属性。默认值为 150 毫秒。

此选项的实现是由对可靠机制的需求驱动的,以便跨不同浏览器处理滚动行为。直到所有浏览器都统一支持 scrollEnd 事件为止。

useScrollendEvent

tsx
useScrollendEvent: boolean
useScrollendEvent: boolean

确定是否使用原生的 scrollend 事件来检测滚动何时停止。如果设置为 false,则使用防抖回退在 isScrollingResetDelay 毫秒后重置 isScrolling 实例属性。默认值为 false

此选项的实现是由对可靠机制的需求驱动的,以便跨不同浏览器处理滚动行为。直到所有浏览器都统一支持 scrollEnd 事件为止。

isRtl

tsx
isRtl: boolean
isRtl: boolean

是否反转水平滚动以支持从右到左的语言环境。

useAnimationFrameWithResizeObserver

tsx
useAnimationFrameWithResizeObserver: boolean
useAnimationFrameWithResizeObserver: boolean

此选项允许将 ResizeObserver 测量包装在 requestAnimationFrame 中,以实现更平滑的更新并减少布局抖动。默认值为 false

它通过确保测量与渲染周期对齐,帮助防止“ResizeObserver 循环完成,但未传递通知”错误。这可以提高性能并减少 UI 抖动,尤其是在动态调整元素大小时。但是,由于 ResizeObserver 已经异步运行,因此添加 requestAnimationFrame 可能会在测量中引入轻微延迟,这在某些情况下可能很明显。如果调整大小操作是轻量级的并且不会导致重排,则启用此选项可能不会提供显着的好处。

Virtualizer 实例

以下属性和方法在 virtualizer 实例上可用

options

tsx
options: readonly Required<VirtualizerOptions<TScrollElement, TItemElement>>
options: readonly Required<VirtualizerOptions<TScrollElement, TItemElement>>

virtualizer 的当前选项。此属性通过您的框架适配器更新,并且是只读的。

scrollElement

tsx
scrollElement: readonly TScrollElement | null
scrollElement: readonly TScrollElement | null

virtualizer 的当前 scrollElement。此属性通过您的框架适配器更新,并且是只读的。

getVirtualItems

tsx
type getVirtualItems = () => VirtualItem[]
type getVirtualItems = () => VirtualItem[]

返回 virtualizer 当前状态的虚拟项目。

getVirtualIndexes

tsx
type getVirtualIndexes = () => number[]
type getVirtualIndexes = () => number[]

返回 virtualizer 当前状态的虚拟行索引。

scrollToOffset

tsx
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

tsx
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

tsx
getTotalSize: () => number
getTotalSize: () => number

返回虚拟化项目的总尺寸(以像素为单位)。如果您选择在渲染元素时动态测量它们,则此测量将逐步更改。

measure

tsx
measure: () => void
measure: () => void

重置任何先前的项目测量。

measureElement

tsx
measureElement: (el: TItemElement | null) => void
measureElement: (el: TItemElement | null) => void

使用您配置的 measureElement virtualizer 选项测量元素。您负责在组件渲染时在 virtualizer 标记中调用此方法(例如,使用类似 React 的 ref 回调 prop),并添加 data-index

tsx
 <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

tsx
resizeItem: (index: number, size: number) => void
resizeItem: (index: number, size: number) => void

手动更改虚拟化项目的大小。使用此函数手动设置为此索引计算的大小。当使用某些自定义变形过渡并且您预先知道变形项目的大小时,这很有用。

您还可以将此方法与节流的 ResizeObserver 而不是 Virtualizer.measureElement 一起使用,以减少重新渲染。

⚠️ 请注意,当使用 Virtualizer.measureElement 监视项目时,手动更改项目的大小将导致不可预测的行为,因为 Virtualizer.measureElement 也在更改大小。但是,您可以在同一 virtualizer 实例中但在不同的项目索引上使用 resizeItem 或 measureElement 之一。

scrollRect

tsx
scrollRect: Rect
scrollRect: Rect

scroll 元素的当前 Rect

shouldAdjustScrollPositionOnItemSizeChange

tsx
shouldAdjustScrollPositionOnItemSizeChange: undefined | ((item: VirtualItem, delta: number, instance: Virtualizer<TScrollElement, TItemElement>) => boolean)
shouldAdjustScrollPositionOnItemSizeChange: undefined | ((item: VirtualItem, delta: number, instance: Virtualizer<TScrollElement, TItemElement>) => boolean)

shouldAdjustScrollPositionOnItemSizeChange 方法可以对动态渲染项目的大小与预估大小不同时滚动位置的调整进行细粒度控制。当在列表中间跳转并向后滚动时,新元素的大小可能与最初预估的大小不同。这种差异可能会导致后续项目发生偏移,从而可能中断用户的滚动体验,尤其是在向后浏览列表时。

isScrolling

tsx
isScrolling: boolean
isScrolling: boolean

布尔标志,指示列表当前是否正在滚动。

scrollDirection

tsx
scrollDirection: 'forward' | 'backward' | null
scrollDirection: 'forward' | 'backward' | null

此选项指示滚动的方向,可能的值为“forward”(向下滚动)和“backward”(向上滚动)。当没有活动滚动时,该值设置为 null。

scrollOffset

tsx
scrollOffset: number
scrollOffset: number

此选项表示沿滚动轴的当前滚动位置。它以像素为单位从可滚动区域的起点测量。

订阅 Bytes

您每周的 JavaScript 新闻。每周一免费发送给超过 100,000 名开发者。

Bytes

无垃圾邮件。随时取消订阅。