Skip to content

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.

ts
interface TreeNode<T extends Record<string, unknown> = Record<string, unknown>> {
  id: string | number
  data: T
  children?: TreeNode<T>[]
  hasChildren?: boolean // true = есть дочерние элементы, которые ещё не загружены
}

Данные строки

FlatTreeRow<T> — область видимости слота содержит:

ts
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 узлов.

ts
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>>>

Пример

vue
<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>