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

Виртуализация списков — это техника оптимизации отображения длинных наборов данных в интерфейсе. Она заключается в том, что в DOM рендерятся только видимые элементы списка, а элементы вне области видимости создаются и удаляются динамически по мере прокрутки. Это позволяет существенно снижать нагрузку на браузер и повышает производительность.

Принципы работы виртуализации

Основная идея виртуализации состоит в следующем:

  • Отображение ограниченного количества элементов. В DOM создаются только те элементы, которые видимы пользователю плюс небольшой буфер для плавной прокрутки.
  • Динамическая подстановка данных. Когда пользователь скроллит список, элементы, вышедшие за пределы видимости, удаляются из DOM, а на их место подставляются новые.
  • Фиксированная высота элементов. Часто используется фиксированная высота каждой строки, что позволяет легко вычислять позиции и смещения элементов без необходимости измерять каждый элемент отдельно.

Преимущества виртуализации

  • Существенное снижение потребления памяти при работе с большими списками.
  • Уменьшение количества операций по обновлению DOM, что повышает FPS.
  • Возможность работать с тысячами элементов без заметных тормозов интерфейса.

Реализация виртуализации в Preact

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

  1. Создание контейнера с прокруткой. Контейнер должен иметь фиксированную высоту и overflow: auto.
const containerStyle = {
  height: '400px',
  overflow: 'auto',
  position: 'relative'
};
  1. Вычисление индексов видимых элементов. Для этого используется высота контейнера и текущая прокрутка (scrollTop).
function getVisibleRange(scrollTop, itemHeight, containerHeight, totalItems) {
  const startIndex = Math.floor(scrollTop / itemHeight);
  const visibleCount = Math.ceil(containerHeight / itemHeight);
  const endIndex = Math.min(startIndex + visibleCount + 2, totalItems);
  return [startIndex, endIndex];
}
  1. Рендер только видимых элементов. Создаётся массив элементов с позиционированием через absolute внутри контейнера.
function VirtualList({ items, itemHeight, containerHeight }) {
  const containerRef = useRef(null);
  const [scrollTop, setScrollTop] = useState(0);

  const onScr oll = (e) => setScrollTop(e.target.scrollTop);

  const [start, end] = getVisibleRange(scrollTop, itemHeight, containerHeight, items.length);
  const visibleItems = items.slice(start, end);

  return (
    <div ref={containerRef} style={{ ...containerStyle, height: containerHeight }} onScr oll={onScroll}>
      <div style={{ height: items.length * itemHeight, position: 'relative' }}>
        {visibleItems.map((item, index) => (
          <div
            key={start + index}
            style={{
              position: 'absolute',
              top: (start + index) * itemHeight,
              height: itemHeight,
              width: '100%'
            }}
          >
            {item}
          </div>
        ))}
      </div>
    </div>
  );
}

Оптимизации и расширенные техники

  1. Буферизация элементов. Для плавной прокрутки часто рендерят несколько элементов за пределами видимой области, чтобы избежать «мерцания» при быстром скролле.

  2. Динамическая высота элементов. В случаях, когда высота элементов неизвестна заранее, применяются техники измерения и кэширования высот, с последующим перерасчётом позиции элементов.

  3. Компоненты высшего порядка (HOC). Создание обёртки над списком позволяет повторно использовать логику виртуализации без дублирования кода.

  4. Использование сторонних библиотек. Для Preact доступны адаптированные библиотеки, такие как preact-virtual-list, обеспечивающие готовую реализацию виртуализации с поддержкой событий и плавного скролла.

Особенности Preact

  • Лёгковесность и скорость. Благодаря минимальному размеру Preact списки рендерятся быстрее, чем в полной версии React, особенно при большом количестве элементов.
  • Совместимость с React. Большинство решений и библиотек для React можно использовать в Preact с помощью preact/compat.
  • Меньшее потребление памяти. Благодаря виртуализации и экономному рендеру компонент Preact позволяет поддерживать плавный интерфейс даже при работе с десятками тысяч элементов.

Виртуализация списков является обязательной практикой при работе с крупными данными и обеспечивает оптимальный баланс между производительностью и удобством пользователя. С применением правильной структуры и продуманного рендеринга Preact позволяет создавать быстрые и отзывчивые интерфейсы, способные обрабатывать огромные объёмы данных без заметных тормозов.