Ленивая загрузка узлов

Ленивая загрузка (Lazy Loading) узлов — это подход, позволяющий загружать данные только по мере необходимости, а не сразу при инициализации компонента. В Element Plus это особенно актуально для компонентов вроде Tree и Cascader, где количество узлов может быть очень большим, а полная загрузка всех данных приведёт к потере производительности.


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

  1. Асинхронная подгрузка данных Узлы дерева загружаются по событию раскрытия родительского узла. При этом используется функция load, которая возвращает промис с массивом дочерних элементов.

  2. Отслеживание состояния узла Каждый узел имеет свойства:

    • loading — индикатор процесса подгрузки;
    • loaded — флаг завершения загрузки;
    • isLeaf — определяет, является ли узел листом (без дочерних элементов).
  3. Управление данными Данные узлов передаются в компонент через data или props, и структура объектов должна поддерживать идентификацию дочерних элементов.


Использование в компоненте Tree

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

<template>
  <el-tree
    :data="treeData"
    :props="defaultProps"
    :load="loadNode"
    lazy
    highlight-current>
  </el-tree>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const treeData = ref([]);

    const defaultProps = {
      children: 'children',
      label: 'label',
      isLeaf: 'isLeaf'
    };

    const loadNode = (node, resolve) => {
      if (node.level === 0) {
        // Корневые узлы загружаем сразу
        resolve([
          { label: 'Категория 1', id: 1 },
          { label: 'Категория 2', id: 2 }
        ]);
      } else {
        // Дочерние узлы загружаем асинхронно
        fetch(`https://api.example.com/nodes?parentId=${node.data.id}`)
          .then(res => res.json())
          .then(children => {
            const formatted = children.map(item => ({
              label: item.name,
              id: item.id,
              isLeaf: item.isLeaf
            }));
            resolve(formatted);
          })
          .catch(() => resolve([]));
      }
    };

    return { treeData, defaultProps, loadNode };
  }
};
</script>

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

  • Атрибут lazy активирует ленивую загрузку.
  • Функция loadNode вызывается при раскрытии узла.
  • Параметр resolve используется для передачи дочерних узлов после асинхронного запроса.

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

В компоненте Cascader ленивую загрузку настраивают через lazy и lazyLoad:

<el-cascader
  :props="cascaderProps"
  :options="options"
  lazy
  :lazy-load="loadCascaderNodes">
</el-cascader>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const options = ref([]);

    const cascaderProps = {
      lazy: true,
      lazyLoad(node, resolve) {
        fetch(`https://api.example.com/cascader?parentId=${node.value || 0}`)
          .then(res => res.json())
          .then(data => {
            resolve(data.map(item => ({
              value: item.id,
              label: item.name,
              leaf: item.isLeaf
            })));
          });
      },
      value: 'value',
      label: 'label',
      children: 'children',
      leaf: 'leaf'
    };

    return { options, cascaderProps, loadCascaderNodes: cascaderProps.lazyLoad };
  }
};
</script>

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

  • В Cascader каждый уровень подгружается отдельно по мере выбора пользователя.
  • Свойство leaf указывает, есть ли у узла дочерние элементы.
  • node.value используется для передачи идентификатора родительского узла.

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

  1. Кэширование данных Чтобы не запрашивать один и тот же узел несколько раз, рекомендуется сохранять загруженные данные в объекте состояния.

  2. Обработка ошибок Всегда предусматривать обработку ошибок сетевых запросов, чтобы пользователь видел пустой или информативный узел вместо зависшего состояния.

  3. Индикатор загрузки Можно использовать встроенные возможности loading у узлов, чтобы визуально показывать процесс подгрузки.

  4. Минимизация размера данных Для больших деревьев загружать только необходимые поля (id, label, isLeaf), остальное подтягивать при необходимости.


Расширенные возможности

  • Динамическое добавление узлов: после первой загрузки можно добавлять дочерние узлы вручную через методы Tree, например append.
  • Программное раскрытие узлов: с помощью методов setCurrentKey или expandNode можно раскрывать узлы по условию.
  • Интеграция с Vuex / Pinia: хранение состояния загруженных узлов в глобальном состоянии позволяет сохранять дерево между переходами страниц.

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