Метод destroy

Метод destroy() в библиотеке Pikaday предназначен для полного уничтожения экземпляра календаря и освобождения связанных с ним ресурсов. После вызова этого метода объект календаря прекращает свою работу, удаляет созданные обработчики событий, скрывает интерфейс выбора даты и исключает дальнейшее взаимодействие с экземпляром.

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

Сигнатура метода проста:

picker.destroy();

Метод не принимает параметров и не возвращает значения.


Зачем необходимо уничтожать экземпляр календаря

При создании объекта Pikaday библиотека выполняет ряд внутренних действий:

  • создаёт DOM-элементы календаря;
  • добавляет обработчики событий мыши и клавиатуры;
  • связывает календарь с полем ввода;
  • отслеживает клики по документу;
  • управляет отображением интерфейса.

Если экземпляр больше не используется, но не уничтожается, в памяти браузера могут оставаться ссылки на объекты и обработчики событий. В небольших проектах это редко становится проблемой, однако в крупных приложениях подобные утечки постепенно накапливаются.

Метод destroy() позволяет корректно завершить жизненный цикл компонента.


Базовый пример использования

Создание календаря:

const picker = new Pikaday({
    field: document.getElementById('date')
});

Уничтожение:

picker.destroy();

После выполнения этого кода календарь перестаёт существовать.


Что происходит внутри destroy()

При вызове метода библиотека выполняет несколько операций.

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

Во время инициализации Pikaday регистрирует множество событий:

input.addEventListener('focus', ...);
document.addEventListener('click', ...);

После вызова destroy() эти обработчики снимаются.

Схематически процесс выглядит так:

picker.destroy();

Результат:

События отключены
↓
Календарь больше не реагирует на действия пользователя

Удаление визуального компонента

Если календарь был добавлен в DOM, метод удаляет соответствующий элемент.

Например, до уничтожения:

<body>
    <input id="date">

    <div class="pika-single">
        ...
    </div>
</body>

После уничтожения:

<body>
    <input id="date">
</body>

Элемент календаря исчезает из документа.


Разрыв внутренних связей

Pikaday хранит ссылки на:

  • поле ввода;
  • контейнер календаря;
  • настройки экземпляра;
  • внутреннее состояние.

После уничтожения эти связи становятся неактуальными и могут быть освобождены сборщиком мусора JavaScript.


Уничтожение перед повторным созданием

Частая ситуация — необходимость создать календарь заново с другими настройками.

Неправильный подход:

let picker = new Pikaday({
    field: input
});

picker = new Pikaday({
    field: input,
    firstDay: 1
});

В этом случае старый экземпляр остаётся в памяти.

Правильный вариант:

picker.destroy();

picker = new Pikaday({
    field: input,
    firstDay: 1
});

Старый объект удаляется корректно, после чего создаётся новый.


Использование в одностраничных приложениях

В современных SPA-приложениях элементы интерфейса постоянно создаются и удаляются.

Пример жизненного цикла компонента:

function mount() {
    picker = new Pikaday({
        field: document.getElementById('date')
    });
}

function unmount() {
    picker.destroy();
}

При закрытии страницы или компонента календарь уничтожается вместе со всеми связанными ресурсами.


Работа с динамически создаваемыми элементами

Рассмотрим форму, которая создаётся программно.

Создание:

const input = document.createElement('input');

document.body.appendChild(input);

const picker = new Pikaday({
    field: input
});

Удаление формы:

picker.destroy();

input.remove();

Такой порядок действий считается безопасным.

Если сначала удалить поле:

input.remove();

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


Проверка перед уничтожением

В сложных приложениях экземпляр может существовать не всегда.

Распространённая практика:

if (picker) {
    picker.destroy();
}

Либо:

picker?.destroy();

Это предотвращает ошибки при обращении к несуществующему объекту.


Повторное открытие после destroy()

После уничтожения экземпляр перестаёт быть рабочим объектом.

Например:

picker.destroy();

picker.show();

Такой код является логической ошибкой.

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

picker.destroy();

picker = new Pikaday({
    field: input
});

Только новый объект может снова отображать календарь.


Отличие destroy() от hide()

Начинающие разработчики часто путают эти методы.

hide()

Скрывает календарь:

picker.hide();

Результат:

  • календарь существует;
  • настройки сохранены;
  • обработчики событий активны;
  • календарь можно показать снова.
picker.show();

destroy()

Полностью удаляет календарь:

picker.destroy();

Результат:

  • интерфейс удалён;
  • события отключены;
  • объект больше не используется;
  • требуется повторное создание экземпляра.

Отличие destroy() от удаления DOM-элемента вручную

Некоторые разработчики пытаются удалить календарь самостоятельно.

Например:

document
    .querySelector('.pika-single')
    .remove();

Внешне календарь исчезнет, однако:

  • обработчики событий останутся;
  • внутренние объекты останутся активными;
  • память может освобождаться некорректно.

Правильный способ:

picker.destroy();

Метод выполняет весь необходимый набор операций.


Использование при смене конфигурации

Предположим, требуется переключаться между двумя вариантами календаря.

Первый режим:

let picker = new Pikaday({
    field: input,
    firstDay: 1
});

Переключение:

picker.destroy();

picker = new Pikaday({
    field: input,
    firstDay: 0
});

Такой подход обеспечивает чистое создание нового экземпляра без накопления лишних объектов.


Уничтожение нескольких календарей

Если на странице присутствует несколько экземпляров Pikaday:

const startPicker = new Pikaday({
    field: startInput
});

const endPicker = new Pikaday({
    field: endInput
});

Каждый экземпляр уничтожается отдельно:

startPicker.destroy();
endPicker.destroy();

Уничтожение одного календаря не влияет на другой.


Типичный сценарий модального окна

Календарь создаётся при открытии окна:

let picker;

function openModal() {
    picker = new Pikaday({
        field: document.getElementById('date')
    });
}

При закрытии окна:

function closeModal() {
    picker.destroy();
}

Если модальное окно открывается много раз, такой подход предотвращает накопление лишних экземпляров.


Возможные ошибки

Создание новых экземпляров без уничтожения старых

Проблемный код:

button.addEventListener('click', () => {
    new Pikaday({
        field: input
    });
});

После нескольких нажатий появится множество экземпляров.

Правильный вариант:

if (picker) {
    picker.destroy();
}

picker = new Pikaday({
    field: input
});

Вызов методов после уничтожения

Ошибка:

picker.destroy();

picker.setDate(new Date());

После удаления экземпляр не должен использоваться.

Лучше сразу создать новый объект:

picker.destroy();

picker = new Pikaday({
    field: input
});

picker.setDate(new Date());

Потеря ссылки на экземпляр

Нежелательный вариант:

new Pikaday({
    field: input
});

Ссылка на объект отсутствует, поэтому позже вызвать destroy() невозможно.

Предпочтительно сохранять экземпляр:

const picker = new Pikaday({
    field: input
});

Практические рекомендации

Всегда уничтожать календарь перед удалением интерфейса

picker.destroy();
container.remove();

Уничтожать экземпляр перед повторной инициализацией

picker.destroy();

picker = new Pikaday(options);

Хранить ссылку на объект

const picker = new Pikaday({
    field: input
});

Не использовать объект после уничтожения

picker.destroy();

После этого экземпляр считается завершившим жизненный цикл и должен быть заменён новым объектом при необходимости дальнейшей работы.


Краткая схема жизненного цикла

Создание:

const picker = new Pikaday({
    field: input
});

Работа:

picker.show();
picker.setDate(new Date());
picker.hide();

Завершение:

picker.destroy();

Цепочка выглядит следующим образом:

Создание экземпляра
        ↓
Использование календаря
        ↓
Скрытие и отображение
        ↓
destroy()
        ↓
Удаление событий
Удаление DOM-элементов
Освобождение ресурсов
Завершение работы экземпляра

Метод destroy() является завершающим этапом жизненного цикла объекта Pikaday и обеспечивает корректное освобождение ресурсов, предотвращение утечек памяти и безопасное удаление календаря из приложения.