Skip to content

VirtualGrid

Виртуальный грид, располагающий элементы по строкам и столбцам. Число столбцов может быть фиксированным либо вычисляться автоматически из columnWidth и ширины контейнера.

Пропы

items

T[]

Массив данных.

columns

number · по умолчанию: 0

Фиксированное число столбцов. Передайте 0 для автовычисления из columnWidth.

columnWidth

number · по умолчанию: 200

Ширина ячейки для автовычисления столбцов.

rowHeight

number · по умолчанию: 200

Высота ячейки в px — начальная оценка при включённом dynamicRowHeight.

gap

number · по умолчанию: 8

Промежуток между ячейками в px.

keyField

string · по умолчанию: 'id'

Поле ключа.

overscan

number · по умолчанию: 2

Дополнительные строки, рендерящиеся вне вьюпорта.

isLoading

boolean · по умолчанию: false

Показывает skeleton, когда items пуст.

motionBlur

boolean · по умолчанию: false

Применить CSS-размытие, масштабируемое по скорости прокрутки при быстрой прокрутке.

dynamicRowHeight

boolean · по умолчанию: false

Измерять реальную высоту каждой строки через ResizeObserver вместо фиксированной rowHeight (высота строки = максимум по ячейкам этой строки).

Слоты

default

Область видимости: { item: T, index: number, row: number, col: number }

Содержимое ячейки.

empty

Область видимости: нет

Показывается, когда items пуст.

skeleton

Область видимости: нет

Показывается при пустом списке и isLoading.

Emits

scroll

Payload: Event

visible-range-change

Payload: { start: number; end: number }

Публичный API

scrollTo(index, options?)

Прокрутить к индексу ячейки. В отличие от scrollTo у остальных компонентов, VirtualGrid вычисляет целевую строку из index и не принимает параметр align.

getScrollElement()

Возвращает элемент, который реально прокручивается — сочетайте с VirtualScrollbar.

ts
gridRef.value?.scrollTo(index)
gridRef.value?.scrollTo(index, { behavior: 'smooth' })
gridRef.value?.getScrollElement() // сочетайте с VirtualScrollbar

Пример

vue
<script setup lang="ts">
import { VirtualGrid } from 'vue-virtual-scroller-kit'

interface Photo {
  id: number
  url: string
  title: string
}

const photos: Photo[] = Array.from({ length: 10_000 }, (_, i) => ({
  id: i,
  url: `https://picsum.photos/seed/${i}/200/200`,
  title: `Photo ${i + 1}`,
}))
</script>

<template>
  <VirtualGrid
    :items="photos"
    :column-width="220"
    :row-height="220"
    :gap="12"
    style="height: 600px"
  >
    <template #default="{ item }">
      <div class="photo-card">
        <img :src="item.url" :alt="item.title" />
        <p>{{ item.title }}</p>
      </div>
    </template>
  </VirtualGrid>
</template>

Динамическая высота строки — когда высота содержимого ячеек различается (например, подписи разной длины), высота строки измеряется по каждой строке, а не фиксируется:

vue
<VirtualGrid
  :items="photos"
  :column-width="220"
  :row-height="220"
  dynamic-row-height
  :gap="12"
  style="height: 600px"
>
  <template #default="{ item }">
    <div class="photo-card" style="height: auto">
      <img :src="item.url" :alt="item.title" />
      <p>{{ item.title }}</p>
      <p v-if="item.caption" class="photo-card__caption">{{ item.caption }}</p>
    </div>
  </template>
</VirtualGrid>

При dynamicRowHeight ячейки больше не получают фиксированную height от грида — задайте им height: auto (либо оставьте height незаданным), чтобы их содержимое определяло реальную высоту строки.