Управление памятью

Shepherd.js — это библиотека для создания интерактивных пошаговых инструкций (туров) на веб-странице. Управление памятью в этой библиотеке играет ключевую роль при разработке сложных интерфейсов с множественными шагами и динамически изменяемыми элементами DOM. Основные аспекты касаются создания, хранения и очистки объектов тура, а также контроля за обработчиками событий.


Создание и хранение объектов тура

Каждый тур в Shepherd.js создается через конструктор new Shepherd.Tour(options). Этот объект содержит массив шагов (steps), а также внутренние состояния:

const tour = new Shepherd.Tour({
  defaultStepOptions: {
    cancelIcon: { enabled: true },
    scrollTo: { beh * avior: 'smooth', block: 'center' }
  }
});

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

  • Шаги добавляются методом tour.addStep(name, options) и сохраняются в массиве tour.steps. При множественных турах необходимо следить за тем, чтобы старые туры удалялись, иначе объекты будут занимать память.
  • Опции шага, такие как attachTo и buttons, создают внутренние ссылки на DOM-элементы. Если эти элементы динамически удаляются с страницы, необходимо вручную отключать шаги перед удалением тура, иначе появятся “висячие” ссылки на DOM.

Управление обработчиками событий

Shepherd.js активно использует события для управления переходами между шагами, а также для взаимодействия с пользовательским интерфейсом. Ключевые события включают:

  • show — шаг отображается на странице.
  • hide — шаг скрывается.
  • complete — тур завершен.
  • cancel — тур отменен.
tour.on('complete', () => {
  console.log('Тур завершен');
});

Проблема утечек памяти возникает, если обработчики остаются активными после удаления тура. Для корректного освобождения памяти нужно использовать метод tour.off(event, handler) или полностью удалять тур через tour.destroy().


Очистка объектов тура

Метод destroy полностью удаляет тур, освобождая память:

tour.destroy();

Что делает destroy:

  1. Отключает все активные обработчики событий.
  2. Удаляет DOM-элементы подсказок.
  3. Очищает массив steps.
  4. Обнуляет внутренние ссылки на элементы, чтобы они могли быть удалены сборщиком мусора.

Если тур используется повторно, рекомендуется после destroy создавать новый объект, вместо повторного использования старого.


Работа с динамическим DOM

Когда шаги привязаны к элементам, которые могут появляться или исчезать динамически, необходимо учитывать:

  • Проверка существования элемента перед вызовом show() шага. Если элемент удален, шаг не будет отображен, но ссылка останется.
  • Удаление шагов, привязанных к элементам, которые исчезли, через tour.removeStep(id) для предотвращения накопления объектов в памяти.
  • Делегирование событий вместо прямой привязки к элементам для снижения числа обработчиков.

Оптимизация для многоступенчатых туров

В проектах с большим числом шагов и туров полезно:

  • Использовать один глобальный объект тура, если структура шагов повторяется, и лишь обновлять содержимое шагов.
  • Минимизировать количество кнопок и обработчиков внутри шага.
  • При завершении или отмене тура обязательно вызывать tour.cancel() и tour.destroy().
  • Избегать долгоживущих ссылок на DOM-элементы внутри пользовательских функций, например в advanceOn или when.

Примеры безопасного управления памятью

const tour = new Shepherd.Tour({ defaultStepOptions: { scrollTo: true } });

tour.addStep('step1', {
  text: 'Пример шага',
  attachTo: { element: '#btn', on: 'bottom' }
});

// Показать шаг
tour.start();

// Завершить тур и очистить память
tour.on('complete', () => {
  tour.destroy();
});
tour.on('cancel', () => {
  tour.destroy();
});

Этот подход гарантирует, что после окончания тура ни один объект не останется в памяти, обработчики событий будут отключены, а DOM-элементы подсказок удалены.


Выводы по управлению памятью

Shepherd.js требует внимательного контроля за объектами тура, шагами и обработчиками событий. Ключевые правила:

  • Всегда удалять тур через destroy() после завершения или отмены.
  • Удалять или обновлять шаги, если связанные DOM-элементы динамически исчезают.
  • Минимизировать создание лишних обработчиков и кнопок внутри шагов.
  • Использовать проверку существования элементов перед вызовом методов показа шага.

Соблюдение этих принципов обеспечивает стабильность приложения и предотвращает утечки памяти при использовании Shepherd.js в сложных интерфейсах.