Хуки жизненного цикла

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


Общая модель жизненного цикла

Жизненный цикл Tom Select представляет собой комбинацию:

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

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


Инициализация экземпляра

Создание экземпляра начинается с вызова конструктора и последующего запуска цепочки инициализации.

Типовая последовательность:

  • создание объекта;
  • сохранение исходного <select>;
  • парсинг опций;
  • подготовка конфигурации;
  • построение структуры UI;
  • привязка событий.

На уровне архитектуры это соответствует следующим этапам:

  • constructor() — создание базового состояния;
  • initialize() — запуск сборки компонента;
  • setup() — подготовка DOM и внутренних структур;
  • setupOptions() — нормализация конфигурации;
  • setupTemplates() — установка шаблонов отображения;
  • setupCallbacks() — регистрация событийных обработчиков.

Смысл стадии: переход от статического HTML-элемента к управляемому компоненту с состоянием.


Конфигурационная фаза

Конфигурация формирует поведение экземпляра до первого рендера.

В этот момент происходят:

  • нормализация входных параметров;
  • объединение дефолтных и пользовательских настроек;
  • подготовка режимов (single, multiple, tags);
  • определение стратегий поиска и загрузки.

Особое значение имеет подготовка опций:

  • синхронные опции (из DOM);
  • асинхронные источники (через load);
  • динамические трансформации данных.

Построение интерфейса

После конфигурации формируется DOM-структура:

  • контейнер компонента;
  • input-элемент управления вводом;
  • dropdown-блок;
  • список опций;
  • контейнер выбранных элементов.

Внутренне этот процесс сопровождается:

  • созданием корневого wrapper;
  • переносом оригинального <select>;
  • генерацией виртуального состояния;
  • первичным рендером через шаблоны.

Шаблоны играют ключевую роль:

  • option — отображение пункта;
  • item — выбранный элемент;
  • dropdown — контейнер списка;
  • no_results — состояние пустого результата.

Событийная модель как часть жизненного цикла

События выступают основным механизмом отслеживания изменений состояния.

Инициализационные события

  • initialize — завершение создания экземпляра;
  • load — загрузка опций из внешнего источника.

События взаимодействия

  • focus / blur — изменение фокуса;
  • type — ввод текста;
  • dropdown_open / dropdown_close — управление списком;
  • change — изменение выбранного значения.

События управления элементами

  • item_add — добавление выбранного элемента;
  • item_remove — удаление элемента;
  • clear — очистка состояния.

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


Обработка ввода и динамическое состояние

При вводе текста активируется цепочка:

  • фиксация значения input;
  • фильтрация списка опций;
  • вызов поиска (score или кастомный filter);
  • обновление dropdown;
  • перерисовка списка.

Ключевой момент — разделение:

  • входное состояние (raw input);
  • вычисленное состояние (filtered options);
  • отображаемое состояние (rendered DOM).

Это позволяет поддерживать масштабируемость при больших наборах данных.


Асинхронная загрузка и расширение жизненного цикла

Механизм load расширяет жизненный цикл за пределы синхронной модели.

Последовательность:

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

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

  • возможность отмены предыдущих запросов;
  • обработка race conditions;
  • кэширование результатов (в зависимости от реализации).

Плагины и хуки расширения

Плагинная система вмешивается в разные стадии жизненного цикла.

Типовые точки расширения:

  • инициализация экземпляра;
  • изменение шаблонов;
  • перехват событий;
  • модификация поведения dropdown;
  • управление item lifecycle.

Плагин может:

  • добавлять новые методы;
  • переопределять существующие;
  • подписываться на события;
  • внедряться в рендеринг.

Ключевая идея: жизненный цикл становится композиционным, а не монолитным.


Управление состоянием выбранных элементов

Добавление и удаление элементов проходит через строгую цепочку:

Добавление

  • проверка валидности значения;
  • проверка лимитов (maxItems);
  • создание item-структуры;
  • добавление в internal state;
  • генерация DOM-узла;
  • триггер item_add.

Удаление

  • поиск элемента в state;
  • удаление из массива значений;
  • удаление DOM-узла;
  • триггер item_remove;
  • синхронизация с исходным <select>.

Перерисовка и синхронизация DOM

Система рендеринга основана на частичных обновлениях:

  • обновление списка опций без полной перезагрузки;
  • перерисовка только изменённых items;
  • синхронизация состояния input и dropdown.

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

  • refreshOptions() — обновление списка;
  • updatePlaceholder() — управление плейсхолдером;
  • sync() — синхронизация с исходным элементом.

Уничтожение экземпляра

Финальная стадия жизненного цикла связана с очисткой ресурсов.

Процедура включает:

  • удаление обработчиков событий;
  • восстановление исходного <select>;
  • удаление созданного DOM;
  • очистку внутренних структур;
  • деактивацию плагинов.

Событие завершения жизненного цикла:

  • destroy

Состояния фокуса и взаимодействия

Фокусная модель влияет на поведение dropdown:

  • активация при focus;
  • раскрытие списка при вводе;
  • закрытие при потере фокуса;
  • сохранение состояния ввода при переключениях.

Особенность заключается в разделении:

  • UI-фокус;
  • логический фокус;
  • состояние выбора.

Внутренние переходы состояний

Жизненный цикл можно представить как конечный автомат:

  • idle → focused → typing → filtering → selecting → updating → idle
  • idle → open dropdown → selecting → close dropdown → idle

Каждый переход сопровождается:

  • изменением state;
  • DOM-обновлением;
  • событием;
  • возможным вызовом плагинов.

Поведение при изменении конфигурации

Некоторые параметры допускают динамическое изменение:

  • обновление списка опций;
  • изменение maxItems;
  • переключение режимов multiple/single.

При изменении конфигурации:

  • пересчитывается state;
  • обновляется UI;
  • пересобираются внутренние индексы;
  • выполняется повторный рендер.

Обработка ошибок внутри жизненного цикла

Ошибочные состояния обрабатываются локально:

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

Инварианты жизненного цикла

Система поддерживает ряд постоянных условий:

  • DOM всегда отражает internal state;
  • выбранные значения синхронизированы с <select>;
  • события вызываются после изменения состояния;
  • рендер не изменяет бизнес-логику.

Эти инварианты обеспечивают предсказуемость поведения при расширении и кастомизации.