Клиентская гидратация в контексте Tom Select представляет собой
процесс восстановления интерактивного состояния компонента на стороне
браузера после серверного рендеринга исходного
<select> элемента или его HTML-аналога. Основная
задача заключается в том, чтобы синхронизировать уже существующую
DOM-структуру с внутренним состоянием экземпляра Tom Select без потери
выбранных значений, пользовательских опций и конфигурации,
сформированной на сервере.
Ключевая особенность гидратации заключается в том, что библиотека не создает интерфейс «с нуля», а «оживляет» уже существующую разметку, минимизируя количество операций над DOM и предотвращая рассинхронизацию между серверным и клиентским состоянием.
При серверном рендеринге формируется стандартный HTML:
<select> с optionselected значенияdisabled состоянияdata-*, содержащие метаданныеTom Select на клиенте должен:
Главная сложность возникает в том, что сервер не знает о внутреннем состоянии Tom Select, а клиент должен корректно интерпретировать уже готовый HTML как источник истины.
Первым шагом является инициализация на уже существующем DOM-узле:
const el = document.querySelector('select');
const control = new TomSelect(el);
На этом этапе библиотека:
Tom Select извлекает данные из DOM:
option.valueoption.textContentoption.selectedoption.disabledДополнительно учитываются пользовательские атрибуты:
data-* для кастомных полейoptgroup структурыСерверное состояние становится базой для построения внутреннего
массива items.
После чтения DOM формируется структура:
items)options)activeItems)Важно, что Tom Select не копирует DOM напрямую, а строит абстракцию поверх него. Это позволяет:
Одной из критических ошибок является повторный вызов конструктора на уже гидратированном элементе.
Без защиты возможны:
Tom Select решает это через внутреннюю привязку экземпляра к DOM-узлу:
if (el.tomselect) {
el.tomselect.destroy();
}
Или через проверку наличия активного инстанса.
При гидратации важно сохранить состояние selected:
single)multiple)Алгоритм:
selected у <option>optionsitemsОсобое внимание уделяется случаям, когда значения отсутствуют в списке опций (например, сервер передал устаревший HTML).
Tom Select поддерживает расширенные поля данных:
labelFieldvalueFieldsearchFieldПри гидратации:
data-*Пример структуры:
{
value: "42",
text: "Option text",
group: "Category A",
custom: "meta"
}
При наличии группировки:
<optgroup label="Fruits">
<option value="1">Apple</option>
</optgroup>
Tom Select строит иерархию:
Важно, что порядок DOM становится источником истины, если не задан
sortField.
В случаях, когда данные подгружаются динамически, гидратация усложняется:
load callbackСтратегия:
Tom Select может работать в нескольких режимах:
<select> скрывается<select>После восстановления состояния активируются обработчики:
changeitem_additem_removedropdown_opendropdown_closeКритично, что события не должны срабатывать во время первичной гидратации, иначе возможны ложные side effects.
Используется флаг инициализации:
this.isInitializing = true;
// гидратация
this.isInitializing = false;
В SPA-архитектурах (React, Vue, Angular без прямой интеграции):
Основная проблема — дублирование инстансов при повторном рендере компонента.
Решение:
destroy()Если сервер передал:
<option value="1" selected>One</option>
а клиент ожидает другое состояние, возникает конфликт при инициализации.
Причины:
valueFieldВозникает при повторной инициализации без очистки предыдущего экземпляра.
При изменении optgroup на клиенте без синхронизации с
сервером нарушается порядок и вложенность.
Повторная инициализация должна приводить к одинаковому результату:
itemsDOM дополняется:
<select data-preload="true" data-initial-value="2"></select>
Это позволяет восстанавливать состояние даже при частично пустом
<select>.
При гидратации применяется логика сравнения:
Различия приводят к приоритету одного источника в зависимости от конфигурации.
При использовании в <form> важно учитывать:
Tom Select поддерживает автоматическое обновление исходного
<select> как источника данных формы, что критично при
отправке POST/GET запросов.
Оптимизация достигается за счет:
Особенно важно при больших списках (1000+ элементов), где полная переработка DOM становится дорогостоящей операцией.
При включенном поиске:
loadСостояние поиска не сохраняется автоматически и должно быть восстановлено отдельно при необходимости.
Если используются кастомные render функции:
Это предотвращает визуальные артефакты при первичном рендере.
Корректная гидратация невозможна без управления состоянием:
Каждый цикл должен гарантировать чистое состояние без утечек памяти и дублирования обработчиков событий.