Реактивность и обновления

Модель состояния и внутренние структуры

Основой реактивности Tom Select является синхронизация трёх слоёв состояния: внутреннего JS-состояния, DOM-представления и внешнего значения поля формы. Каждый из этих слоёв может изменяться независимо, но библиотека стремится поддерживать их консистентность через единый слой управления состоянием.

Внутреннее состояние включает:

  • список доступных опций (options)
  • список выбранных элементов (items)
  • текущий текст поиска (query)
  • состояние загрузки удалённых данных (loading)
  • активный фокус и навигацию по списку

Любое изменение состояния проходит через методы API, а не напрямую через DOM, что позволяет сохранять предсказуемость поведения и упрощает обновления интерфейса.


Принцип управляемых изменений

Обновления в Tom Select не происходят через прямое вмешательство в DOM-узлы. Вместо этого используется событийно-методная модель:

  • изменение данных → обновление состояния → перерисовка UI
  • UI-события → обработка → изменение состояния → синхронизация внешнего значения

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

Ключевые методы, влияющие на реактивность:

  • setValue(value) — установка выбранного значения
  • addItem(value) — добавление элемента в выбранные
  • removeItem(value) — удаление элемента
  • clear() — сброс выбора
  • clearOptions() — очистка списка опций
  • addOption(data) — динамическое добавление опции

Каждый из этих методов запускает цепочку обновлений UI и событий.


Двусторонняя синхронизация значения

Формальное значение select-элемента остаётся источником внешней синхронизации. Tom Select поддерживает двустороннюю связь:

  • изменение через API → обновляет скрытое input-значение
  • изменение input (например, программное или через форму) → обновляет внутреннее состояние

При этом используется механизм защиты от циклических обновлений. Внутренний флаг состояния блокирует повторную реакцию на собственные изменения.


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

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

  • изменения могут агрегироваться в одну операцию
  • DOM обновляется один раз после завершения серии изменений
  • события эмиссии группируются или подавляются при необходимости

Особое значение имеют “тихие” обновления:

  • setValue(value, true) — обновление без вызова событий
  • addItem(value, true) — добавление без триггера onchange
  • refreshItems() — принудительная синхронизация отображения

Такие режимы позволяют выполнять массовые операции без перегрузки UI.


Реактивность списка опций

Список опций является динамической структурой, особенно при использовании удалённых источников данных (remote data). При добавлении новых данных происходит:

  1. обновление internal options map
  2. пересчёт фильтров поиска
  3. перерисовка dropdown
  4. сохранение позиции скролла (при необходимости)

Методы, влияющие на опции:

  • addOption(data) — добавление одной записи
  • addOptions(array) — массовое добавление
  • clearOptions() — полная очистка
  • refreshOptions(triggerDropdown) — пересборка списка

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


Реакция на пользовательский ввод

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

  • событие input
  • обновление query
  • фильтрация options
  • пересборка dropdown
  • пересчёт highlighted item

Фильтрация может быть:

  • локальной (client-side)
  • удалённой (server-side через load callback)

Во втором случае реактивность расширяется за пределы UI и включает сетевой слой.


Событийная система как часть реактивности

Реактивность реализуется через событийную модель. Основные события:

  • change — изменение выбранного значения
  • item_add — добавление элемента
  • item_remove — удаление элемента
  • dropdown_open / dropdown_close
  • type — ввод текста
  • load — загрузка данных

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

События генерируются строго после завершения внутреннего обновления, что гарантирует консистентность состояния в момент обработки.


Перерисовка DOM и виртуализация состояния

Tom Select не использует полноценный виртуальный DOM, однако применяет локальные оптимизации:

  • частичное обновление списка элементов
  • переиспользование DOM-узлов
  • минимизация операций innerHTML
  • обновление только изменённых элементов

Например, при добавлении одного item не происходит полной перерисовки контейнера — обновляется только соответствующий элемент и счётчики состояния.


Инвалидация и принудительное обновление

В ряде случаев требуется принудительно синхронизировать состояние UI и данных:

  • изменение options напрямую через API без стандартных методов
  • внешнее обновление модели данных
  • восстановление состояния после сериализации

Используются методы:

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

Эти операции применяются как точечная инвалидация, а не как полная перерисовка компонента.


Конфликты состояния и их разрешение

Реактивная модель предусматривает возможные конфликты:

  • удалённая опция остаётся в selected items
  • значение формы изменено извне
  • асинхронные данные приходят в изменённом порядке
  • пользователь вводит данные во время загрузки

Стратегия разрешения:

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

Производительность реактивных обновлений

Реактивность напрямую связана с производительностью. Основные оптимизации:

  • минимизация layout thrashing
  • кеширование отфильтрованных результатов
  • отложенная перерисовка dropdown
  • debounce ввода пользователя
  • reuse DOM nodes для items

При больших наборах данных ключевым фактором становится не количество элементов, а частота реактивных обновлений. Именно поэтому batching операций критически важен для стабильной работы интерфейса.


Итоговая модель реактивности

Реактивность Tom Select строится как управляемый цикл:

событие → изменение состояния → нормализация → частичное обновление DOM → эмиссия событий

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