Внутренняя модель конфигурации Tom Select строится как многоуровневая система объединения источников настроек, где итоговое поведение компонента определяется не отдельным параметром, а результатом разрешения конфликтов между несколькими слоями данных. Каждый слой имеет собственный приоритет, а также особенности применения в момент инициализации и в рантайме. Понимание порядка применения настроек критично для предсказуемого поведения экземпляра и предотвращения скрытых переопределений.
На нижнем уровне находятся встроенные значения по умолчанию. Это полный набор параметров, определяющих поведение компонента без внешнего вмешательства. Они включают:
Эти значения формируют базовый контракт компонента. Любая инициализация, даже полностью пустая, опирается на этот слой. Он никогда не модифицируется напрямую, а используется как исходная точка для последующего слияния.
Следующий уровень — объект параметров, передаваемый при создании экземпляра Tom Select через JavaScript API. Этот слой обладает высоким приоритетом и является основным способом управления поведением компонента.
new TomSelect("#select", {
maxItems: 3,
create: true,
sortField: "text"
});
Значения, переданные таким образом, не заменяют базовую конфигурацию целиком, а накладываются поверх неё. При этом используется неглубокое или частично глубокое слияние в зависимости от типа параметра. Простые типы (boolean, string, number) полностью перезаписывают значения по умолчанию, тогда как структурные параметры (например, callbacks или объекты настроек рендеринга) могут быть объединены частично либо заменены целиком в зависимости от внутренней логики обработки.
Особенность данного слоя заключается в том, что он применяется до анализа DOM-атрибутов, но после загрузки базовых дефолтов.
Tom Select способен извлекать часть настроек непосредственно из
HTML-разметки исходного элемента <select>. Этот слой
часто используется в декларативной модели и имеет более высокий
приоритет по сравнению с дефолтами, но более низкий по сравнению с
параметрами инициализации JavaScript.
Пример:
<select id="select" multiple data-max-items="5" data-create="true">
В данном случае значения data-* атрибутов
интерпретируются как конфигурационные параметры. Внутренний механизм
преобразует строковые значения DOM в соответствующие типы данных.
Например:
"true" → true"false" → falsenumberЭтот слой особенно важен при прогрессивной деградации интерфейса, когда компонент должен работать без явного JavaScript-конфига.
При столкновении значений из HTML и объекта инициализации применяется строгий приоритет:
data-* атрибуты HTMLТаким образом, любые настройки, заданные программно, всегда переопределяют декларативные атрибуты. Это обеспечивает предсказуемость поведения при динамической инициализации, когда один и тот же DOM может использоваться с разными конфигурациями.
Плагины в Tom Select не просто расширяют функциональность, но также способны вмешиваться в конфигурационную модель. Каждый подключённый плагин может:
Пример подключения:
new TomSelect("#select", {
plugins: ["remove_button", "dropdown_input"]
});
Плагины применяются после формирования базовой конфигурации, но до полной инициализации экземпляра. Их влияние может затрагивать как поведение, так и структуру доступных опций. Важно, что конфликт между плагинами и пользовательскими настройками разрешается в пользу пользовательского объекта инициализации, если явно не указано обратное внутри плагина.
Некоторые параметры представляют собой сложные структуры: объекты рендеринга, функции обработки событий, колбэки загрузки данных. Для них применяется особая логика:
render: {
option: function(data, escape) {
return `<div>${escape(data.text)}</div>`;
}
}
Если базовая конфигурация содержит рендеры, а пользователь задаёт только часть ключей, поведение зависит от типа переопределения:
render предыдущие значения
теряютсяНа практике чаще применяется стратегия полной замены объекта
render, что упрощает предсказуемость.
Колбэки вроде onChange, onInitialize,
onItemAdd также подчиняются приоритету полной замены. Если
в конфигурации указан новый обработчик, он полностью заменяет
предыдущий.
После инициализации экземпляра конфигурация перестаёт быть статической. Через API можно изменять поведение компонента, однако приоритеты в этом случае меняются.
const select = new TomSelect("#select");
select.setValue("1");
select.settings.placeholder = "Новый текст";
select.sync();
При рантайм-изменениях важно различать:
settings — текущая активная конфигурация
экземпляраИзменение settings вручную не всегда приводит к
немедленному применению. В большинстве случаев требуется вызов методов
синхронизации (sync, refreshOptions,
clearCache), которые пересчитывают внутреннее
состояние.
Отдельный слой конфигурации связан с загрузкой данных
(load, preload, options). Здесь
также существует система приоритетов:
load callbackoptionsaddOption)Если включён асинхронный режим, загруженные данные могут временно перекрывать статические значения, но при последующем обновлении источника статические опции возвращаются в приоритет.
Методы API обладают собственным уровнем воздействия, который часто рассматривается как отдельный верхний слой над конфигурацией.
select.addOption({ value: "new", text: "New item" });
Добавленные таким образом данные становятся частью текущего состояния
и могут перекрывать исходные options, особенно если
совпадает ключ value.
Метод setValue не изменяет конфигурацию, но изменяет
состояние, которое может влиять на визуальное поведение и триггеры
событий. Это косвенно влияет на восприятие конфигурации, но не входит в
её иерархию.
Сводная модель разрешения конфликтов параметров выглядит следующим образом:
Эта иерархия не является линейной в строгом математическом смысле, поскольку отдельные подсистемы (рендеринг, данные, события) имеют собственные под-иерархии, но в большинстве практических сценариев именно эта модель определяет итоговое поведение.
Изменение параметров с высоким приоритетом может приводить к неожиданным эффектам:
Особенно заметно это при изменении параметров, связанных с
render и load, поскольку они затрагивают сразу
несколько слоёв внутренней архитектуры.
В случае множественных экземпляров Tom Select на странице конфигурация не наследуется автоматически между инстансами. Каждый экземпляр формирует собственную цепочку приоритетов, начиная с базовых дефолтов. Однако общие паттерны часто повторяются, что создаёт иллюзию глобальной конфигурации, хотя фактически её нет.
При использовании фабричных функций или обёрток над инициализацией может формироваться внешний слой, который задаёт единые настройки для группы экземпляров, но внутри Tom Select он не имеет специального статуса и рассматривается как обычный JavaScript-объект инициализации.
Если один и тот же параметр задан в нескольких слоях, разрешение происходит строго по приоритету. Например:
data-max-items="2"maxItems: 5nullИтоговое значение будет 5, поскольку
JavaScript-конфигурация перекрывает остальные источники. Даже если HTML
задан позже в DOM-структуре, он не влияет на уже применённый
JS-конфиг.
Такая модель обеспечивает стабильность поведения независимо от способа интеграции компонента в приложение.