Tree структуры

В библиотеке Floating UI Tree-структуры применяются для управления вложенными элементами интерфейса, такими как многоуровневые меню, всплывающие панели или тултипы, которые могут иметь зависимые позиции друг от друга. Tree-структура позволяет эффективно вычислять положения элементов относительно их родителей и учитывать ограничения по видимости, смещению и коллизиям.

Ключевые компоненты Tree:

  • Node – отдельный элемент дерева, содержащий информацию о позиции, размере и связи с родителем.
  • Parent Node – элемент, который управляет поведением дочерних элементов и их вычислением.
  • Floating Tree – структура, объединяющая все узлы и позволяющая централизованно контролировать позиционирование.

Инициализация Tree

Создание дерева начинается с инициализации корневого узла. Для этого используется функция createFloatingTree():

import { createFloatingTree, createFloating } from '@floating-ui/dom';

const tree = createFloatingTree();

const reference = document.querySelector('#button');
const floating = document.querySelector('#tooltip');

const { x, y, update } = createFloating({
  reference,
  floating,
  strategy: 'absolute',
  middleware: [],
  whileElementsMounted: tree.addNode
});

Пояснение:

  • tree.addNode регистрирует текущий floating-узел в дереве.
  • whileElementsMounted следит за жизненным циклом DOM-элементов и обновляет позиции автоматически при изменениях.

Связь Parent–Child

Дочерние узлы получают позицию относительно своего родителя. Это особенно важно для многоуровневых меню:

const parentNode = createFloating({ reference: parentButton });
const childNode = createFloating({ reference: childButton });

tree.addNode(parentNode);
tree.addNode(childNode, parentNode);

Особенности:

  • Дочерний узел (childNode) наследует ограничения по смещению и коллизии от parentNode.
  • Любое перемещение или изменение позиции родителя автоматически пересчитывает положение дочернего узла.

Middleware и Tree

Floating UI использует middleware для управления поведением узлов в дереве. Ключевые middleware, которые работают с Tree:

  • offset() – добавляет смещение между узлом и родителем.
  • flip() – меняет положение узла при пересечении границ видимой области.
  • shift() – корректирует позицию, чтобы элемент оставался в пределах видимости.
  • size() – автоматически подбирает размеры дочерних узлов, учитывая ограничения родителя.

Пример применения:

import { offset, flip, shift } from '@floating-ui/dom';

createFloating({
  reference: childButton,
  floating: childTooltip,
  middleware: [
    offset(8),
    flip(),
    shift({ padding: 5 })
  ],
  whileElementsMounted: tree.addNode
});

Управление жизненным циклом узлов

Tree-структура обеспечивает автоматическое удаление узлов при удалении DOM-элементов:

const { destroy } = createFloating({
  reference,
  floating,
  whileElementsMounted: tree.addNode
});

// При необходимости удаления узла
destroy();

Преимущества:

  • Нет необходимости вручную отслеживать DOM-изменения.
  • Все зависимости в дереве остаются корректными при динамическом добавлении или удалении элементов.

Анимации и Tree

Tree-структуры позволяют синхронизировать анимации всплывающих элементов. Использование whileElementsMounted позволяет:

  • Начать анимацию появления после вычисления позиции.
  • Корректировать анимацию при изменении позиции родителя.

Пример с использованием CSS-переходов:

const node = createFloating({
  reference,
  floating,
  whileElementsMounted: tree.addNode
});

node.update(); // вычисление позиции перед запуском анимации
floating.style.transition = 'opacity 0.2s ease';
floating.style.opacity = '1';

Советы по оптимизации Tree

  1. Минимизировать количество middleware для каждого узла, чтобы ускорить расчёт позиции.
  2. Использовать whileElementsMounted для автоматического контроля узлов и предотвращения утечек памяти.
  3. Для вложенных меню обязательно указывать родителя при добавлении узла, чтобы правильно работала логика коллизий.
  4. При динамическом изменении размеров элементов использовать autoUpdate() для пересчёта позиций.

Применение Tree в сложных интерфейсах

Tree-структуры в Floating UI позволяют строить:

  • Многоуровневые контекстные меню.
  • Динамические тултипы с зависимыми подсказками.
  • Всплывающие панели, которые «следуют» за родительским элементом при скролле или изменении размеров.

Эффективное использование Tree обеспечивает согласованное и плавное позиционирование всех элементов, сокращает количество ручных вычислений и упрощает поддержку сложных интерфейсов.