Кастомная виртуализация
useVirtualScroll() — низкоуровневый composable, на котором работают все компоненты. Используйте его, когда нужно построить кастомный виртуальный контейнер.
type SizeProvider = number | ((index: number) => number)
function useVirtualScroll(options: UseVirtualScrollOptions): UseVirtualScrollReturnОпции
itemCount
number | Ref<number>
Общее число элементов.
estimatedItemSize
SizeProvider | Ref<SizeProvider> · по умолчанию: 50
Оценочная высота элемента: число или (index) => number. Ref вызывает полную перестройку при изменении.
overscan
number · по умолчанию: 3
Дополнительные элементы, рендерящиеся вне вьюпорта.
getScrollElement
() => HTMLElement | null
Возвращает контейнер прокрутки.
pageMode
boolean · по умолчанию: false
Использовать window как контейнер прокрутки. Считывается один раз, не реактивно — см. примечание ниже.
horizontal
boolean · по умолчанию: false
Виртуализировать scrollLeft/clientWidth вместо scrollTop/clientHeight, RTL-безопасно через normalizeScrollLeft. Считывается один раз, не реактивно — см. примечание ниже.
motionBlur
boolean · по умолчанию: false
Отслеживать скорость прокрутки и предоставлять её как blurAmount (px). По умолчанию выключено — нулевая стоимость при отключении.
pageModeиhorizontalсчитываются изoptionsодин раз при настройке composable — изменение их на живом инстансе не даёт эффекта. Если нужно переключить оси во время выполнения, перемонтируйте компонент, вызывающийuseVirtualScroll(например, через:key).
Возвращаемое значение
visibleRange
Readonly<Ref<VisibleRange>>
{ start, end } — индексы первого и последнего видимых элементов.
totalHeight
Readonly<Ref<number>>
Общий прокручиваемый размер в px по оси прокрутки (высота, либо ширина при horizontal).
offsetTop
(index: number) => number
Пиксельное смещение элемента по индексу вдоль оси прокрутки (top, либо left при horizontal).
scrollTo
(index, align?, options?) => void
Прокрутить к элементу ('start' | 'center' | 'end' | 'auto'). options.behavior — 'auto' (по умолчанию, мгновенно) или 'smooth'.
scrollToOffset
(offset: number, options?) => void
Прокрутить к сырому пиксельному смещению. Тот же options.behavior.
measureItem
(index, height) => void
Сообщить измеренную высоту строки.
handleScroll
() => void
Вручную запустить пересчёт видимого диапазона.
blurAmount
Readonly<Ref<number>>
Текущий радиус motion-blur в px. Всегда 0, если опция motionBlur не включена.
Пример
<script setup lang="ts">
import { computed, ref } from 'vue'
import { useVirtualScroll } from 'vue-virtual-scroller-kit'
const ITEMS = Array.from({ length: 50_000 }, (_, i) => `Item ${i + 1}`)
const containerRef = ref<HTMLElement | null>(null)
const { visibleRange, totalHeight, offsetTop } = useVirtualScroll({
itemCount: ITEMS.length,
estimatedItemSize: 40,
getScrollElement: () => containerRef.value,
})
</script>
<template>
<div ref="containerRef" style="height: 500px; overflow-y: auto; position: relative">
<div :style="{ height: `${totalHeight}px`, position: 'relative' }">
<div
v-for="i in visibleRange.end - visibleRange.start + 1"
:key="visibleRange.start + i - 1"
:style="{
position: 'absolute',
top: `${offsetTop(visibleRange.start + i - 1)}px`,
width: '100%',
height: '40px',
}"
>
{{ ITEMS[visibleRange.start + i - 1] }}
</div>
</div>
</div>
</template>