Управление жизненным циклом

Жизненный цикл календаря Pikaday начинается с создания экземпляра, в момент которого формируется внутреннее состояние компонента, привязываются DOM-элементы и устанавливаются обработчики событий. Конструктор принимает конфигурационный объект и на его основе определяет поведение будущего календаря: режим выбора даты, ограничения диапазона, форматирование и привязку к полю ввода.

При инициализации выполняются следующие ключевые действия:

  • создание контейнера календаря в памяти;
  • вычисление начального состояния даты;
  • подготовка шаблона UI;
  • регистрация событий (click, keydown, focus и др.);
  • привязка к input-элементу (если он указан).

В этот момент экземпляр существует как связка логики и DOM, но ещё не обязательно добавлен в документ. Важно различать создание объекта и его отображение: календарь может быть инициализирован в скрытом состоянии до первого показа.

Привязка к DOM и первичная отрисовка

После создания экземпляра происходит этап интеграции с DOM-структурой. Если в конфигурации указан field, библиотека связывает календарь с конкретным input-элементом и синхронизирует значения.

Основные операции на этом этапе:

  • установка значения input при наличии defaultDate;
  • синхронизация внутреннего состояния с внешним значением поля;
  • подготовка контейнера календаря к вставке в документ;
  • привязка обработчиков фокуса и клика.

Рендеринг в Pikaday происходит лениво: HTML-структура календаря формируется либо при первом открытии, либо сразу при инициализации, в зависимости от конфигурации. Это влияет на производительность и поведение при загрузке страницы.

Открытие и закрытие календаря

Состояние видимости является одним из ключевых элементов жизненного цикла. Календарь может быть открыт через вызов метода show() или автоматически при взаимодействии с input-элементом.

При открытии происходят следующие шаги:

  • вычисление позиции относительно привязанного элемента;
  • проверка ограничений (minDate, maxDate);
  • обновление текущего месяца/года;
  • рендеринг сетки дней;
  • добавление календаря в DOM (если он ещё не добавлен);
  • активация глобальных обработчиков (например, закрытие по клику вне области).

Закрытие календаря выполняется методом hide() и включает:

  • скрытие DOM-контейнера;
  • деактивацию глобальных обработчиков;
  • сохранение текущего состояния;
  • прекращение обработки событий клавиатуры.

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

Управление состоянием даты

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

Основные методы управления:

  • setDate(date, triggerChange) — установка выбранной даты;
  • getDate() — получение текущего значения;
  • gotoDate(date) — переход к месяцу, содержащему указанную дату.

При вызове setDate выполняется цепочка операций:

  • обновление внутреннего состояния;
  • пересчёт отображаемого месяца;
  • обновление выделенного дня;
  • синхронизация с input-элементом;
  • опциональный вызов событий onSelect и onChange.

Эта логика обеспечивает согласованность между визуальным состоянием и данными.

Обновление интерфейса и перерисовка

Рендеринг календаря отделён от логики состояния. Это позволяет выполнять частичные обновления без полной пересборки DOM.

Перерисовка инициируется в случаях:

  • смена месяца или года;
  • изменение выбранной даты;
  • изменение ограничений (min/max);
  • смена локали или формата отображения.

Процесс обновления включает:

  • пересчёт дней месяца;
  • генерацию новой сетки календаря;
  • обновление классов активных и недоступных дней;
  • переработку заголовка (месяц/год).

Оптимизация рендера в Pikaday достигается за счёт минимизации операций с DOM: чаще всего заменяется только содержимое таблицы дней, без пересоздания всего контейнера.

Работа с ограничениями и динамическими изменениями

Жизненный цикл включает поддержку динамического изменения конфигурации. Некоторые параметры могут быть изменены после инициализации:

  • setMinDate(date)
  • setMaxDate(date)
  • setStartRange(date)
  • setEndRange(date)

При изменении ограничений выполняется пересчёт допустимых значений и обновление интерфейса. Это влияет на:

  • доступность отдельных дат;
  • визуальное отображение диапазонов;
  • поведение навигации по месяцам.

Если текущая выбранная дата становится недопустимой, она автоматически корректируется или сбрасывается в зависимости от конфигурации.

Подписка на события и реакция системы

Событийная модель является основой взаимодействия с календарём. В процессе жизненного цикла активируются следующие типы событий:

  • onSelect — выбор даты;
  • onOpen — открытие календаря;
  • onClose — закрытие календаря;
  • onDraw — перерисовка интерфейса.

Каждое событие вызывается в строго определённый момент жизненного цикла. Например, onDraw срабатывает после завершения построения DOM, что позволяет безопасно модифицировать интерфейс.

Система событий встроена в ядро Pikaday и не требует внешнего event-emitter. Это упрощает управление состоянием, но требует аккуратного контроля за побочными эффектами.

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

Завершающий этап жизненного цикла связан с корректным удалением календаря из памяти и DOM. Метод destroy() выполняет полную деинициализацию.

Последовательность действий при уничтожении:

  • удаление DOM-элемента календаря;
  • отключение всех событий (click, keydown, focus);
  • разрыв связи с input-элементом;
  • очистка внутренних ссылок на состояние;
  • предотвращение дальнейших вызовов методов.

После вызова destroy экземпляр становится нерабочим. Любые обращения к методам могут приводить к ошибкам или игнорированию вызова.

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

Повторная инициализация и переиспользование

В некоторых сценариях требуется пересоздание календаря с новым набором параметров. Прямой «перезапуск» экземпляра не предусмотрен, поэтому используется схема:

  • вызов destroy;
  • создание нового экземпляра с обновлённой конфигурацией.

Такой подход гарантирует чистое состояние без остаточных данных.

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

Поведение в SPA и компонентах UI

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

Типичные сценарии:

  • инициализация при монтировании компонента;
  • обновление при изменении props;
  • уничтожение при размонтировании.

Ключевая особенность заключается в необходимости строгого соответствия между DOM-деревом приложения и экземплярами календаря. Несоблюдение этого приводит к «висящим» обработчикам и неконсистентному состоянию.

Состояние между открытиями

Между вызовами show() и hide() календарь сохраняет внутренние данные:

  • текущий месяц;
  • выбранную дату;
  • активный элемент навигации;
  • позицию в DOM.

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

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

Управление фокусом и клавиатурной навигацией

В течение жизненного цикла активно используется управление фокусом. При открытии календаря фокус может перемещаться на первый доступный день, а при закрытии возвращаться в input.

Клавиатурная навигация включает:

  • перемещение по дням;
  • переключение месяцев;
  • выбор даты через Enter;
  • закрытие через Escape.

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