Древовидная структура компонентов

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

import { NTree } from 'naive-ui'

const treeData = [
  {
    key: '1',
    label: 'Корневой узел',
    children: [
      { key: '1-1', label: 'Дочерний узел 1' },
      { key: '1-2', label: 'Дочерний узел 2' }
    ]
  },
  {
    key: '2',
    label: 'Второй корневой узел'
  }
]

В n-tree ключи (key) уникальны и служат идентификаторами узлов. Это критично для корректной работы методов добавления, удаления и поиска элементов.

<NTree :data="treeData" :default-expanded-keys="['1']" />

Настройка и расширение узлов

Каждый узел дерева может содержать следующие параметры:

  • key — уникальный идентификатор узла.
  • label — текстовое отображение узла.
  • children — массив дочерних узлов.
  • disabled — блокировка выбора узла.
  • isLeaf — явно обозначает узел как лист (отсутствие дочерних узлов).
  • extra — дополнительный слот для кастомного контента рядом с меткой узла.

Пример с кастомизацией узла:

const treeData = [
  {
    key: '1',
    label: 'Папка 1',
    extra: h('span', { style: { color: 'gray' } }, '3 файла'),
    children: [
      { key: '1-1', label: 'Файл A', isLeaf: true },
      { key: '1-2', label: 'Файл B', isLeaf: true }
    ]
  }
]

Выбор узлов и множественный выбор

Naive UI поддерживает несколько режимов выбора:

  • Одиночный выбор — по умолчанию.
  • Множественный выбор — включается через checkable.
  • Режим с каскадным выборомcheck-strictly позволяет выбирать дочерние элементы независимо от родителя.
<NTree
  :data="treeData"
  checkable
  :checked-keys="['1-1']"
  check-strictly
/>

При использовании checkable возвращается объект с массивом ключей выбранных узлов, что удобно для синхронизации с состоянием приложения.

Динамическая подгрузка данных

Для больших деревьев желательно использовать ленивую загрузку узлов через load:

const loadNode = async (node) => {
  if (node.level === 0) return [
    { key: 'root-1', label: 'Ленивая папка', isLeaf: false }
  ]
  return [
    { key: `${node.key}-1`, label: 'Дочерний узел', isLeaf: true }
  ]
}

<NTree :load="loadNode" />

Преимущество такого подхода — экономия ресурсов и ускорение начальной загрузки, особенно при работе с тысячами узлов.

Стилизация и слоты

Naive UI предоставляет гибкость кастомизации:

  • label слот для полного контроля над отображением текста.
  • prefix и suffix слоты для добавления иконок или кнопок.
  • Динамическое изменение стиля через class и style.

Пример с иконкой перед узлом:

<NTree :data="treeData">
  <template #prefix="{ node }">
    <i class="icon-folder"></i>
  </template>
</NTree>

Обработка событий

Основные события дерева:

  • onUpdate:expanded-keys — при изменении раскрытых узлов.
  • onUpdate:checked-keys — при выборе/снятии выбора.
  • onNodeClick — при клике на узел.
  • onNodeToggle — при раскрытии/сворачивании узла.

Пример обработки клика:

<NTree :data="treeData" @onNodeCl ick="handleClick" />

function handleClick(node) {
  console.log('Кликнут узел:', node.label)
}

Фильтрация и поиск

Компонент n-tree поддерживает поиск по дереву с помощью свойства filter. Фильтрация может быть кастомной:

<NTree :data="treeData" :filter="filterTree" />

function filterTree(node, keyword) {
  return node.label.includes(keyword)
}

Практические советы

  • Использовать уникальные key даже для динамически создаваемых узлов.
  • Применять ленивую загрузку при большом объеме данных.
  • Разделять слоты для кастомного отображения меток и кнопок.
  • Выбирать подходящий режим выбора, чтобы избежать путаницы при каскадных операциях.

Этот подход позволяет создавать эффективные и интерактивные деревья, которые легко масштабируются и интегрируются в современные приложения на Vue 3 с использованием Naive UI.