Виртуальная прокрутка и видимость
О чём эта страница
В DOM рендерятся только строки внутри области просмотра. Этот набор определяют две вещи:
- Структурная видимость — ни один предок узла не свёрнут.
assembly/tree-visibility.tsперестраивает флагиshownвсего дерева за один проход и стеком, который отслеживаетrightNodeсвёрнутых предков, вместо подъёма по цепочке для каждого узла. Очистка поиска использует тот же путь, поэтому «загрязнение»shownпосле поиска не остаётся. - Геометрическая видимость —
scrollTopи высота контейнера вырезают диапазон[start, end).
MPTT делает оба шага дешёвыми:
| Операция | Сложность |
|---|---|
| Проверка поддерева | O(1) — сравнение диапазона leftNode / rightNode |
| Срез области просмотра | O(k), k — число строк в области |
| Развёртывание / свёртывание одного узла | O(поддерево + log N) |
Параметры
| prop | Тип | По умолчанию | Описание |
|---|---|---|---|
height | string | '100%' | Высота контейнера. У родителя должна быть определённая высота, иначе нечего вырезать |
width | string | '100%' | Ширина контейнера |
lineHeight | number | 26 | Высота строки в пикселях; виртуальная прокрутка пересчитывает её в видимый диапазон |
fontSize | string | '14px' | Размер шрифта внутри строк |
Развёртывание / свёртывание и анимация
expandAll()/collapseAll()действуют на текущее представление: обычно на всё дерево, а во время поиска — только на текущие результаты, не меняя состояние основного дерева.- При развёртывании или свёртывании создаётся короткий переход (около 220 мс) только для строк ветвей, уже находящихся в области просмотра; всё поддерево в DOM ради анимации не добавляется, а неизменившиеся строки не перемонтируются.
- Во время перехода прокрутка кратко блокируется, чтобы анимация не обрывалась посередине.
- При включённом
prefers-reduced-motionанимация становится мгновенной.
Использование
vue
<script setup lang="ts">
import { ref } from 'vue'
import { VueGiantTree } from 'vue3-giant-tree-wasm'
const treeRef = ref<InstanceType<typeof VueGiantTree>>()
const selected = ref([])
</script>
<template>
<div style="height: 600px">
<button @click="treeRef?.expandAll()">Развернуть всё</button>
<button @click="treeRef?.collapseAll()">Свернуть всё</button>
<VueGiantTree ref="treeRef" :tree="rows" root="root" v-model="selected" />
</div>
</template>Попробуйте
Переключите «Размер данных» на 10k, нажмите «Развернуть всё» и прокрутите: строк в дереве тысячи, а число строк в DOM всегда зависит только от высоты области просмотра.