Виртуализация списков

Проблема масштабирования DOM при больших наборах данных

При работе с выпадающими списками, содержащими тысячи или десятки тысяч элементов, основным узким местом становится DOM-дерево. Каждая опция в стандартном <select> или кастомном dropdown превращается в отдельный DOM-узел, который:

  • увеличивает время первичного рендеринга;
  • усложняет перерасчёт layout и repaint;
  • замедляет обработку событий (hover, focus, click);
  • повышает потребление памяти браузера.

Даже при оптимизированном CSS и минимальной логике JavaScript, список из 10 000 элементов может приводить к заметной задержке открытия dropdown и прокрутки.

В контексте Tom Select это особенно критично, поскольку библиотека создаёт расширенный UI поверх стандартного select: поиск, теги, группировки, кастомный рендеринг опций.


Суть виртуализации (windowing) в списках

Виртуализация списка основана на принципе отображения только видимой части данных. Вместо создания 10 000 DOM-элементов создаётся небольшой «окно»-набор, например:

  • 20–50 элементов для видимой области;
    • небольшой буфер сверху и снизу (overscan).

При прокрутке:

  • DOM-узлы переиспользуются;
  • контент подменяется;
  • позиционирование пересчитывается.

Это позволяет свести нагрузку на DOM к постоянной величине независимо от общего размера данных.


Архитектурные ограничения dropdown в Tom Select

Внутренняя модель dropdown в Tom Select состоит из нескольких ключевых компонентов:

  • контейнер списка (dropdown_content);
  • элементы опций (option);
  • система рендеринга (render);
  • слой поиска (score / search);
  • кеширование данных опций.

Без виртуализации каждая опция создаётся как DOM-элемент через render.option() и добавляется в контейнер. При больших данных это приводит к линейному росту нагрузки.


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

Ограничение количества рендеримых элементов

Простейший способ оптимизации — ограничение числа отображаемых опций:

  • отображение только первых N результатов;
  • динамическое обновление при вводе текста;
  • использование maxOptions или аналогичных ограничителей.

Однако этот подход не решает проблему прокрутки и полного доступа к данным.


Серверная фильтрация как альтернатива полной загрузке

При больших наборах данных часто используется стратегия:

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

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

В Tom Select это часто комбинируется с load() функцией, которая подгружает результаты по мере ввода.


Виртуализация как слой поверх рендеринга

Полноценная виртуализация в контексте dropdown реализуется как промежуточный слой между:

  • массивом данных (source of truth);
  • DOM-контейнером списка.

Логика включает:

  1. вычисление видимого диапазона элементов;
  2. сопоставление индексов данных с DOM-элементами;
  3. повторное использование DOM-узлов;
  4. обновление содержимого через innerHTML или render-функции.

Принцип windowing на уровне dropdown

Пусть имеется список:

items = [0, 1, 2, 3, ... 9999]

При высоте строки 30px и высоте контейнера 300px:

  • одновременно видно ~10 элементов;
  • добавляется overscan = 5 сверху и снизу;
  • итоговый рендер: 20 элементов.

При прокрутке:

  • startIndex смещается;
  • endIndex пересчитывается;
  • DOM обновляется без пересоздания всего списка.

Пример псевдореализации виртуального окна

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

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

Ключевые точки интеграции:

  • переопределение render.option;
  • контроль вставки элементов в dropdown_content;
  • перехват событий scroll;
  • синхронизация состояния поиска.

Кэширование DOM-узлов

Одним из критичных элементов оптимизации является повторное использование DOM-элементов:

  • вместо удаления старых элементов используется переработка;
  • создаётся пул элементов (pooling);
  • обновляется только текст и dataset.

Это снижает нагрузку на GC и уменьшает количество layout thrashing.


Особенности работы с группами (optgroups)

При наличии группировок:

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

В таких случаях диапазон вычисляется не по индексам массива, а по «плоскому» списку, где группы и элементы объединены в одну последовательность.


Оптимизация поиска в связке с виртуализацией

Поиск в Tom Select влияет на виртуализацию следующим образом:

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

Типичный поток:

  1. ввод символа;
  2. пересчёт score;
  3. обновление массива результатов;
  4. перерасчёт window;
  5. ререндер только видимого окна.

Производительность и стоимость операций

Основные источники нагрузки без виртуализации:

  • создание DOM-элементов (O(n));
  • layout recalculation;
  • repaint при открытии dropdown;
  • обработка событий наведения.

С виртуализацией:

  • DOM операций становится O(k), где k — размер окна;
  • память стабилизируется;
  • scroll остаётся линейным, но ограниченным фиксированным окном.

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

Несмотря на эффективность, виртуализация имеет ограничения:

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

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


Гибридные стратегии

На практике часто используется комбинация подходов:

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

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