Пользовательские шаблоны узлов

Element Plus предоставляет гибкий механизм для работы с деревьями компонентов через компонент ElTree. Одним из самых мощных инструментов является возможность использования пользовательских шаблонов узлов, что позволяет полностью контролировать отображение каждого элемента дерева.


Основные принципы

По умолчанию ElTree отображает дерево, используя простой текст из поля label объекта данных. Чтобы кастомизировать отображение, применяется слот default для узлов:

<el-tree
  :data="treeData"
  node-key="id"
  :props="defaultProps"
>
  <template #default="{ node, data }">
    <div style="display: flex; align-items: center;">
      <span style="font-weight: bold;">{{ data.label }}</span>
      <span style="margin-left: auto; color: gray;">{{ data.info }}</span>
    </div>
  </template>
</el-tree>

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

  • node — объект TreeNode, содержащий информацию о состоянии узла, включая методы для раскрытия/сворачивания, выбранного состояния и т.д.
  • data — оригинальный объект из массива treeData.
  • Слот default позволяет использовать любую HTML-разметку и Vue-компоненты внутри узла.

Использование динамических компонентов

Для сложных интерфейсов удобно рендерить разные компоненты внутри узлов, в зависимости от типа данных:

<el-tree :data="treeData" node-key="id" :props="defaultProps">
  <template #default="{ node, data }">
    <component :is="getComponent(data.type)" :data="data" />
  </template>
</el-tree>

<script>
import FileNode from './components/FileNode.vue';
import FolderNode from './components/FolderNode.vue';

export default {
  methods: {
    getComponent(type) {
      return type === 'file' ? FileNode : FolderNode;
    }
  }
}
</script>

Такой подход позволяет поддерживать разные визуальные представления узлов, при этом сохраняя функциональность дерева.


Доступ к состоянию узла

Через объект node доступны методы и свойства для управления узлом:

  • node.expanded — проверка состояния раскрытия.
  • node.level — уровень вложенности.
  • node.setChecked(boolean) — программная установка состояния выбора.
  • node.isLeaf — проверка, является ли узел листом.
  • node.parent — родительский узел.

Пример условного изменения стиля для раскрытых узлов:

<template #default="{ node, data }">
  <div :style="{ backgroundColor: node.expanded ? '#f0f9eb' : '#fff' }">
    {{ data.label }}
  </div>
</template>

Вложенные слоты и кастомизация иконок

Element Plus позволяет полностью переопределять иконки раскрытия через слот toggle:

<el-tree :data="treeData" node-key="id" :props="defaultProps">
  <template #toggle="{ node }">
    <i v-if="node.expanded" class="el-icon-minus"></i>
    <i v-else class="el-icon-plus"></i>
  </template>
  <template #default="{ node, data }">
    {{ data.label }}
  </template>
</el-tree>
  • Слот toggle заменяет стандартную стрелку на любую иконку или компонент.
  • Это особенно полезно при разработке кастомных деревьев с корпоративным стилем.

Асинхронная загрузка данных узлов

Часто требуется подгружать данные динамически. Для этого используется событие load в комбинации с пользовательским шаблоном:

<el-tree
  :data="treeData"
  :props="defaultProps"
  :load="loadNode"
  lazy
  node-key="id"
>
  <template #default="{ node, data }">
    <span>{{ data.label }}</span>
    <span v-if="node.loading" style="color: gray;">Загрузка...</span>
  </template>
</el-tree>

<script>
export default {
  methods: {
    loadNode(node, resolve) {
      setTimeout(() => {
        resolve([
          { id: node.data.id + '-1', label: 'Дочерний узел' }
        ])
      }, 1000);
    }
  }
}
</script>
  • lazy — активирует ленивую загрузку.
  • resolve — функция для передачи загруженных данных обратно дереву.
  • Состояние node.loading можно использовать для отображения индикатора загрузки прямо в пользовательском шаблоне.

Поддержка событий на уровне узла

С помощью пользовательского шаблона можно навешивать события на отдельные элементы:

<template #default="{ node, data }">
  <div @click="onClickNode(node, data)" style="cursor: pointer;">
    {{ data.label }}
  </div>
</template>

<script>
export default {
  methods: {
    onClickNode(node, data) {
      console.log('Выбран узел:', data.label);
      node.setChecked(!node.checked);
    }
  }
}
</script>
  • Возможность комбинировать визуальную кастомизацию и логическую обработку событий.
  • node.setChecked позволяет изменять состояние выбора без модификации исходного массива данных.

Стилизация отдельных узлов

Использование :class и :style прямо в слоте default позволяет стилизовать узлы в зависимости от условий:

<template #default="{ node, data }">
  <div
    :class="{ 'is-selected': node.checked }"
    :style="{ color: data.type === 'folder' ? 'blue' : 'black' }"
  >
    {{ data.label }}
  </div>
</template>
  • Классы и инлайн-стили могут быть динамическими, на основе состояния узла или данных.
  • Позволяет создавать интерактивные и визуально информативные деревья.

Использование пользовательских шаблонов с компонентами Element Plus

Элементы интерфейса Element Plus можно внедрять прямо в узлы:

<template #default="{ data }">
  <el-tag type="success">{{ data.label }}</el-tag>
</template>
  • Поддерживаются все компоненты Element Plus, включая el-button, el-badge, el-avatar.
  • Можно строить интерактивные панели управления прямо внутри дерева.

Пользовательские шаблоны узлов предоставляют полную свободу кастомизации и позволяют строить комплексные интерфейсы на базе ElTree, сохраняя при этом функциональность управления состоянием узлов и событийную логику.