VirtualTree
Дерево с раскрытием/сворачиванием, настраиваемым отступом на уровень вложенности и опциональной ленивой (асинхронной) загрузкой дочерних элементов.
Пропы
nodes
TreeNode<T>[]
Корневые узлы.
indent
number · по умолчанию: 20
Отступ в px на уровень вложенности.
estimatedItemSize
number · по умолчанию: 36
Оценочная высота строки.
overscan
number · по умолчанию: 5
Дополнительные строки, рендерящиеся вне вьюпорта.
onLoadChildren
(node) => Promise<TreeNode<T>[]>
Вызывается при первом раскрытии узла с hasChildren: true.
motionBlur
boolean · по умолчанию: false
Применить CSS-размытие, масштабируемое по скорости прокрутки при быстрой прокрутке.
Узел дерева
TreeNode<T> — форма каждой записи в пропе nodes.
interface TreeNode<T extends Record<string, unknown> = Record<string, unknown>> {
id: string | number
data: T
children?: TreeNode<T>[]
hasChildren?: boolean // true = есть дочерние элементы, которые ещё не загружены
}Данные строки
FlatTreeRow<T> — область видимости слота содержит:
interface FlatTreeRow<T> {
node: TreeNode<T>
depth: number
isExpanded: boolean
hasChildren: boolean
isLoading: boolean // true, пока выполняется onLoadChildren
}Слоты
default
Область видимости: { row: FlatTreeRow<T>, index: number }
Кастомное содержимое строки. Кнопка раскрытия рендерится самим компонентом.
empty
Область видимости: нет
Пустое состояние.
Emits
node-expand
Payload: TreeNode<T>
node-collapse
Payload: TreeNode<T>
node-click
Payload: [TreeNode<T>, depth: number]
Публичный API
expandAll()
Раскрыть все узлы, включая уже загруженные вложенные.
collapseAll()
Свернуть все узлы.
scrollTo(index, align?, options?)
Прокрутить к плоскому индексу строки. align — 'start' | 'center' | 'end' | 'auto'.
getScrollElement()
Возвращает элемент, который реально прокручивается — сочетайте с VirtualScrollbar.
expandedIds
Readonly<Ref<Set<string | number>>> — текущие раскрытые ID узлов.
treeRef.value?.expandAll()
treeRef.value?.collapseAll()
treeRef.value?.scrollTo(index, 'start')
treeRef.value?.scrollTo(index, 'start', { behavior: 'smooth' })
treeRef.value?.getScrollElement() // сочетайте с VirtualScrollbar
treeRef.value?.expandedIds // Readonly<Ref<Set<string | number>>>Пример
<script setup lang="ts">
import { VirtualTree } from 'vue-virtual-scroller-kit'
import type { TreeNode, FlatTreeRow } from 'vue-virtual-scroller-kit'
interface FileNode {
name: string
type: 'file' | 'folder'
}
const nodes: TreeNode<FileNode>[] = [
{
id: 1,
data: { name: 'src', type: 'folder' },
children: [
{ id: 2, data: { name: 'main.ts', type: 'file' } },
{ id: 3, data: { name: 'App.vue', type: 'file' } },
],
},
{
id: 4,
data: { name: 'node_modules', type: 'folder' },
hasChildren: true, // ленивая загрузка
},
]
async function loadChildren(node: TreeNode<FileNode>): Promise<TreeNode<FileNode>[]> {
const res = await fetch(`/api/children/${node.id}`)
return res.json()
}
</script>
<template>
<VirtualTree
:nodes="nodes"
:indent="20"
:on-load-children="loadChildren"
style="height: 400px"
@node-click="(node, depth) => console.log(node.data.name, depth)"
>
<template #default="{ row }">
<span>{{ row.node.data.type === 'folder' ? '📁' : '📄' }} {{ row.node.data.name }}</span>
</template>
</VirtualTree>
</template>