VirtualList
Віртуалізований список із фіксованою висотою рядка — рендерить лише видиме вікно діапазону з overscan-запасом.
Приклад
Всередині сцени — 10 000 рядків; у DOM їх менше кількох десятків: списком керує позиція скролу, а не розмір масиву.
API
Props
| Назва | Тип | Типово | Опис |
|---|---|---|---|
items* | T[] | — | Масив рядків. Порядок у масиві — порядок на екрані, компонент його не міняє. |
itemHeight* | number | — | Висота КОЖНОГО рядка в пікселях (число, не рядок). Це контракт компонента, а не налаштування: уся арифметика віртуалізації — позиція діапазону, зміщення рядків, загальна висота полотна — обчислюється множенням на це число. Рядки іншої висоти ламають розрахунок: останні екрани списку або не показуються, або показуються з дірками. Рядок має гарантовано вкладатися у задану висоту (`truncate`, `line-clamp-*`, фіксована кількість рядків тексту). |
height | string | "20rem" | Висота контейнера прокрутки, напр. `"16rem"`. |
overscan | number | 5 | Скільки рядків за межами видимої зони тримати відрендереними з кожного боку. Більший overscan — плавніший скрол, більший DOM. |
keyField | string | "id" | Поле-ідентифікатор рядка для `:key`. |
ariaLabel | string | "Віртуальний список" | Доступна назва scrollable-списку. |
Слоти
| Назва | Опис |
|---|---|
item | Обов'язковий рендер одного рядка. Висоту рядку задає сам компонент. |
Доступно через ref
| Назва | Тип | Опис |
|---|---|---|
scrollToIndex | (index: number) => void | Прокрутити до рядка за номером у `items` (центр вікна). |
Слоти
Єдиний слот — item, і він обов'язковий: без нього списку нема чим
малювати. Слот отримує { item, index } (index — абсолютний номер у
items, а не позиція у вікні) і рендерить вміст ОДНОГО рядка. Висоту
рядка задає сам компонент (itemHeight), тож у слоті не можна покладатися
на min-h чи py- — рядок має вкладатися у відведені пікселі:
<UiVirtualList ref="list" :items="items" :item-height="36">
<template #item="{ item, index }">
<div class="flex items-center px-3">{{ index }}. {{ item.label }}</div>
</template>
</UiVirtualList>
Програмна прокрутка — list.value.scrollToIndex(index): рядок опиняється
посередині вікна, позиція клаймиться в межі полотна. При різкому
скороченні items стара позиція скролу, що вилізла за нове полотно,
скидається на початок — інакше вікно діапазону рахувалося б із «висячого»
scrollTop і список показував би порожнє місце.
Коли використовувати
Для довгих однорідних списків — логів, стрічок платіжок, результатів пошуку, — де рендер всіх рядків означає тисячі зайвих вузлів DOM. Разом з UiPagination: пагінація зменшує обсяг даних, віртуалізація — кількість відрендерених вузлів.
Коли НЕ використовувати
Контракт фіксованої висоти. itemHeight — не налаштування, а
передумова: уся арифметика віртуалізації (позиція діапазону, зміщення
рядків, загальна висота полотна) обчислюється множенням на це число.
Змінна висота рядків ламає розрахунок — останні екрани списку або не
показуються, або показуються з дірками. Рядки різної висоти — це не
«складніший випадок», а інший компонент.
Для коротких списків до кількох сотень рядків: звичайний v-for дешевший
за вимірювання скролу, а браузер сам впорається з кількома сотнями вузлів.
Доступність
Прокрутка контейнера доступна з клавіатури як звичайна зона скролу
(overflow-y-auto). Рядки — абсолютні прямокутники з координатами
top = index * itemHeight, тож порядок у DOM відповідає порядку на
екрані; ключ рядків береться з keyField, щоб фокус і стан рядка не
загубилися під час перемальовування вікна.