Виртуализация списков — это техника оптимизации отображения больших массивов данных в интерфейсе, позволяющая рендерить только те элементы, которые видны пользователю в данный момент, вместо полного списка. Atomico, как современная библиотека для создания веб-компонентов на базе Web Components и реактивного подхода, предоставляет гибкие возможности для реализации виртуализированных списков.
Ключевая идея виртуализации состоит в управлении видимым диапазоном элементов. Вместо создания DOM-узлов для всех элементов списка, компонент хранит полный массив данных, но в DOM рендерятся только элементы, попадающие в область видимости. При прокрутке диапазон обновляется динамически.
Основные элементы виртуализации:
Atomico использует реактивные состояния через
useState и useEffect, что идеально подходит
для виртуализации. Пример структуры состояния:
import { c, useState, useEffect, useRef } from "atomico";
function VirtualList({ items, itemHeight, containerHeight }) {
const [scrollTop, setScrollTop] = useState(0);
const containerRef = useRef();
const visibleCount = Math.ceil(containerHeight / itemHeight);
const startIndex = Math.floor(scrollTop / itemHeight);
const endIndex = Math.min(startIndex + visibleCount + 2, items.length);
const visibleItems = items.slice(startIndex, endIndex);
useEffect(() => {
const handleScroll = () => setScrollTop(containerRef.current.scrollTop);
const el = containerRef.current;
el.addEventListener("scroll", handleScroll);
return () => el.removeEventListener("scroll", handleScroll);
}, []);
return (
<host>
<div
ref={containerRef}
style={{
height: `${containerHeight}px`,
overflowY: "auto",
position: "relative"
}}
>
<div style={{ height: `${items.length * itemHeight}px`, position: "relative" }}>
{visibleItems.map((item, index) => (
<div
style={{
position: "absolute",
top: `${(startIndex + index) * itemHeight}px`,
height: `${itemHeight}px`,
width: "100%"
}}
>
{item}
</div>
))}
</div>
</div>
</host>
);
}
export const virtualList = c(VirtualList);
В этом примере:
containerRef отслеживает прокрутку.scrollTop — текущее смещение, которое используется для
расчета видимого диапазона.Для списков с десятками тысяч элементов важно:
useMemo для вычисления видимых элементов.scroll для снижения нагрузки.Пример добавления буфера и мемоизации:
import { useMemo } from "atomico";
const buffer = 2;
const visibleItems = useMemo(() => {
const start = Math.max(startIndex - buffer, 0);
const end = Math.min(endIndex + buffer, items.length);
return items.slice(start, end);
}, [startIndex, endIndex, items]);
Если элементы имеют переменную высоту, стандартная виртуализация с абсолютным позиционированием не подходит. Для Atomico применим подход с хранением кумулятивной высоты:
top позиции
каждого элемента.Такой подход требует дополнительного состояния и рефов для отслеживания высоты, но сохраняет производительность при больших списках.
Atomico позволяет интегрировать виртуализированный список с слотами и пользовательскими компонентами:
<div style={{ height: "400px", overflowY: "auto" }}>
<slot name="item" />
</div>
Это позволяет передавать шаблон рендеринга элемента извне, сохраняя реактивность и гибкость.
Виртуализация списков полезна при:
Atomico, благодаря реактивной модели и поддержке Web Components, позволяет создавать модульные и легко настраиваемые виртуализированные компоненты, которые интегрируются в любые проекты без зависимости от фреймворков вроде React или Vue.
Хорошее понимание принципов виртуализации и их реализация через Atomico дает возможность создавать высокопроизводительные интерфейсы даже при огромных объемах данных, сохраняя плавность и отзывчивость приложения.