Skip to content

虚拟化

介绍

@cat-kit/fe 的虚拟化能力聚焦为单个 Virtualizer 类。它负责:

  • 计算可视范围与总尺寸
  • 接收真实测量结果并增量修正布局
  • 提供 mountmeasureElementscrollToIndexsubscribe 等适合 Vue composable 包装的薄 API

它支持 vertical 与 horizontal 两种单轴模式,但不内置 grid/masonry。

快速使用

typescript
import { Virtualizer } from '@cat-kit/fe'

const virtualizer = new Virtualizer({ count: 10_000, overscan: 6, estimateSize: () => 44 })

virtualizer.setViewport(480)
virtualizer.setOffset(120)

const snapshot = virtualizer.getSnapshot()
console.log(snapshot.items, snapshot.totalSize)

如果已经拿到容器元素,也可以直接挂载:

typescript
virtualizer.mount(containerEl)
virtualizer.measureElement(index, itemEl)

交互示例

下面的 demo 会实时展示 scrollToIndex、当前可见范围以及实际渲染项数量。示例会先按卡片档位给出较接近真实值的 estimateSize,目标项挂载后再补一次对齐,同时保留不等高 item,方便直观看到 measureElement 对异高列表的修正效果。

vue
异高 item 演示

这里会先按卡片档位给出一个预估高度,再由 `measureElement` 用真实 DOM 尺寸继续校正。这样既能保留异高 item 的演示效果,也不会让远距离 `scrollToIndex` 因估算偏差而明显跳偏。

可见范围:等待挂载渲染项:0 / 500beforeSize:0pxafterSize:87500px

API参考

构造参数

typescript
interface VirtualizerOptions {
  count?: number
  overscan?: number
  horizontal?: boolean
  paddingStart?: number
  paddingEnd?: number
  initialOffset?: number
  initialViewport?: number
  estimateSize?: (index: number) => number
  onChange?: (snapshot: VirtualSnapshot) => void
}

常用实例方法

typescript
virtualizer.setCount(2000)
virtualizer.setViewport(600)
virtualizer.setOffset(320)
virtualizer.measure(12, 88)
virtualizer.measureElement(12, element)
virtualizer.scrollToIndex(120, { align: 'center' })
virtualizer.scrollToOffset(2400)
virtualizer.mount(containerEl)
virtualizer.unmount()

快照结构

typescript
interface VirtualSnapshot {
  items: VirtualItem[]
  range: { startIndex: number; endIndex: number } | null
  totalSize: number
  beforeSize: number
  afterSize: number
  offset: number
  viewportSize: number
  horizontal: boolean
  isScrolling: boolean
}

Vue 封装建议

  • 在容器 onMounted 时调用 mount
  • 使用 subscribeonChange 把快照同步到 ref
  • 在每个 item 的 ref 回调里调用 measureElement(index, el)
  • 渲染时优先使用 beforeSize + items + afterSize 的块状布局

基于 MIT 许可发布