При работе с выпадающими списками, содержащими тысячи или десятки
тысяч элементов, основным узким местом становится DOM-дерево. Каждая
опция в стандартном <select> или кастомном dropdown
превращается в отдельный DOM-узел, который:
Даже при оптимизированном CSS и минимальной логике JavaScript, список из 10 000 элементов может приводить к заметной задержке открытия dropdown и прокрутки.
В контексте Tom Select это особенно критично, поскольку библиотека создаёт расширенный UI поверх стандартного select: поиск, теги, группировки, кастомный рендеринг опций.
Виртуализация списка основана на принципе отображения только видимой части данных. Вместо создания 10 000 DOM-элементов создаётся небольшой «окно»-набор, например:
При прокрутке:
Это позволяет свести нагрузку на DOM к постоянной величине независимо от общего размера данных.
Внутренняя модель dropdown в Tom Select состоит из нескольких ключевых компонентов:
dropdown_content);option);render);score / search);Без виртуализации каждая опция создаётся как DOM-элемент через
render.option() и добавляется в контейнер. При больших
данных это приводит к линейному росту нагрузки.
Простейший способ оптимизации — ограничение числа отображаемых опций:
maxOptions или аналогичных
ограничителей.Однако этот подход не решает проблему прокрутки и полного доступа к данным.
При больших наборах данных часто используется стратегия:
В таком режиме виртуализация может быть не обязательна, так как DOM никогда не содержит полный набор данных.
В Tom Select это часто комбинируется с load() функцией,
которая подгружает результаты по мере ввода.
Полноценная виртуализация в контексте dropdown реализуется как промежуточный слой между:
Логика включает:
innerHTML или
render-функции.Пусть имеется список:
items = [0, 1, 2, 3, ... 9999]
При высоте строки 30px и высоте контейнера 300px:
При прокрутке:
function getVisibleRange(scrollTop, itemHeight, containerHeight, overscan = 5) {
const start = Math.floor(scrollTop / itemHeight);
const visibleCount = Math.ceil(containerHeight / itemHeight);
return {
start: Math.max(0, start - overscan),
end: start + visibleCount + overscan
};
}
function renderWindow(items, range) {
const fragment = document.createDocumentFragment();
for (let i = range.start; i < range.end && i < items.length; i++) {
const el = document.createElement('div');
el.className = 'option';
el.textContent = items[i].text;
fragment.appendChild(el);
}
return fragment;
}
Внутри Tom Select рендеринг опций обычно отделён от логики данных. Это позволяет внедрять виртуализацию без изменения источника данных.
Ключевые точки интеграции:
render.option;dropdown_content;Одним из критичных элементов оптимизации является повторное использование DOM-элементов:
Это снижает нагрузку на GC и уменьшает количество layout thrashing.
При наличии группировок:
В таких случаях диапазон вычисляется не по индексам массива, а по «плоскому» списку, где группы и элементы объединены в одну последовательность.
Поиск в Tom Select влияет на виртуализацию следующим образом:
Типичный поток:
Основные источники нагрузки без виртуализации:
С виртуализацией:
Несмотря на эффективность, виртуализация имеет ограничения:
В контексте Tom Select это особенно заметно при кастомных шаблонах опций, где высота элементов может меняться.
На практике часто используется комбинация подходов:
Такая модель позволяет удерживать стабильную производительность даже при сложных сценариях использования dropdown.