GroupedVirtualList
Рендерит элементы, сгруппированные под сворачиваемыми заголовками секций. Каждая группа может раскрываться или сворачиваться с плавной CSS-анимацией.
Пропы
groups
GroupDef<T>[]
Массив определений групп.
estimatedItemSize
number · по умолчанию: 50
Оценочная высота строк элементов.
estimatedGroupHeaderSize
number · по умолчанию: 40
Оценочная высота строк заголовков групп — используется отдельно от estimatedItemSize, чтобы более высокий или низкий стиль заголовка не сбивал расчёт позиции прокрутки до измерения.
overscan
number · по умолчанию: 3
Дополнительные строки, рендерящиеся вне вьюпорта.
keyField
string · по умолчанию: 'id'
Поле, используемое как ключ элемента.
motionBlur
boolean · по умолчанию: false
Применить CSS-размытие, масштабируемое по скорости прокрутки при быстрой прокрутке.
stickyGroupHeaders
boolean · по умолчанию: false
Держать заголовок текущей группы прикреплённым сверху, пока её элементы прокручиваются под ним (оверлей, см. ниже).
stickyGroupHeadersрендерится как постоянный оверлей над списком, переиспользуя слот#group-headerдля той группы, что сейчас находится вверху вьюпорта — это не настоящая CSS-строкаposition: sticky, что здесь невозможно, поскольку виртуализированные строки —position: absolute. Он мгновенно перескакивает к следующей группе (без анимации «выталкивания»).
Определение группы
GroupDef<T> — форма каждой записи в пропе groups.
interface GroupDef<T> {
key: string // уникальный идентификатор группы
label: string // отображаемая метка
items: T[] // элементы в этой группе
collapsed?: boolean // начальное состояние свёрнутости
}Слоты
group-header
Область видимости: { group: GroupDef<T>, toggle: () => void, isCollapsed: boolean }
Кастомный заголовок группы.
default
Область видимости: { item: T, index: number, groupKey: string }
Содержимое строки элемента.
empty
Область видимости: нет
Показывается, когда все группы пусты.
Emits
Те же, что у VirtualList: scroll, visible-range-change.
Публичный API (GroupedVirtualListExpose)
toggle(groupKey)
Раскрыть/свернуть группу.
scrollTo(index, align?, options?)
Прокрутить к плоскому индексу строки.
getScrollElement()
Возвращает элемент, который реально прокручивается — сочетайте с VirtualScrollbar.
import type { GroupedVirtualListExpose } from 'vue-virtual-scroller-kit'
const listRef = ref<GroupedVirtualListExpose | null>(null)
listRef.value?.toggle('group-key') // раскрыть/свернуть группу
listRef.value?.scrollTo(index) // прокрутить к плоскому индексу строки
listRef.value?.scrollTo(index, 'start', { behavior: 'smooth' })
listRef.value?.getScrollElement() // сочетайте с VirtualScrollbarПример
<script setup lang="ts">
import { ref } from 'vue'
import { GroupedVirtualList } from 'vue-virtual-scroller-kit'
import type { GroupDef, GroupedVirtualListExpose } from 'vue-virtual-scroller-kit'
interface Contact {
id: number
name: string
email: string
}
const groups = ref<GroupDef<Contact>[]>([
{
key: 'a',
label: 'A',
items: [
{ id: 1, name: 'Alice', email: 'alice@example.com' },
{ id: 2, name: 'Aaron', email: 'aaron@example.com' },
],
},
{
key: 'b',
label: 'B',
items: [{ id: 3, name: 'Bob', email: 'bob@example.com' }],
collapsed: true,
},
])
const listRef = ref<GroupedVirtualListExpose | null>(null)
function expandAll() {
groups.value = groups.value.map((g) => ({ ...g, collapsed: false }))
}
function collapseAll() {
groups.value = groups.value.map((g) => ({ ...g, collapsed: true }))
}
</script>
<template>
<button @click="expandAll">Expand all</button>
<button @click="collapseAll">Collapse all</button>
<GroupedVirtualList
ref="listRef"
:groups="groups"
:estimated-item-size="56"
style="height: 500px"
>
<template #group-header="{ group, toggle, isCollapsed }">
<div class="group-header" @click="toggle">
{{ isCollapsed ? '▶' : '▼' }} {{ group.label }}
<span>({{ group.items.length }})</span>
</div>
</template>
<template #default="{ item }">
<div class="contact-row">
<strong>{{ item.name }}</strong>
<span>{{ item.email }}</span>
</div>
</template>
</GroupedVirtualList>
</template>