Как на JS реализовать «бесконечную прокрутку» (Infinite Scroll) с использованием Intersection Observer API?
Бесконечная прокрутка (Infinite Scroll) — популярный UX-паттерн, при котором новый контент подгружается автоматически по мере того, как пользователь достигает конца страницы. Intersection Observer API — современный и производительный способ отслеживать видимость элементов в области просмотра без постоянных вычислений через события scroll.
## Базовая реализация
### 1. HTML-разметка
Создайте контейнер для элементов и сигнальный элемент-триггер в конце списка:
html
### 2. JavaScript-код
javascript
const contentList = document.getElementById(‘content-list’);
const sentinel = document.getElementById(‘sentinel’);
let page = 1;
let isLoading = false;
// Функция загрузки данных
async function loadMoreItems() {
if (isLoading) return;
isLoading = true;
try {
const response = await fetch(`https://api.example.com/items?page=${page}`);
const data = await response.json();
if (data.items.length === 0) {
observer.disconnect(); // Больше данных нет — отключаем наблюдатель
return;
}
data.items.forEach(item => {
const el = document.createElement(‘div’);
el.className = ‘item’;
el.textContent = item.title;
contentList.appendChild(el);
});
page++;
} catch (error) {
console.error(‘Ошибка загрузки:’, error);
} finally {
isLoading = false;
}
}
// Создание наблюдателя
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
loadMoreItems();
}
});
}, {
root: null, // viewport
rootMargin: ‘0px’,
threshold: 0.1 // срабатывает при 10% видимости
});
// Начинаем наблюдать за сигнальным элементом
observer.observe(sentinel);
// Загружаем первую порцию данных
loadMoreItems();
## Ключевые параметры IntersectionObserver
— **root** — элемент-контейнер для отслеживания (null = viewport).
— **rootMargin** — отступы вокруг root, например `’200px’` позволит загружать данные заранее, до того как пользователь достигнет конца.
— **threshold** — доля видимости элемента (0–1), при которой срабатывает callback.
## Советы по оптимизации
1. **Флаг isLoading** — предотвращает дублирующиеся запросы при быстрой прокрутке.
2. **rootMargin: ‘200px’** — подгружайте контент заранее, чтобы пользователь не ждал.
3. **Отключение observer** — вызывайте `observer.disconnect()` когда данные закончились.
4. **Виртуализация DOM** — при очень большом количестве элементов используйте библиотеки типа `virtual-scroll` для удаления невидимых узлов из DOM.
5. **Debounce/throttle** — при необходимости ограничьте частоту вызовов функции загрузки.
## Преимущества перед scroll-событием
Intersection Observer не блокирует главный поток, работает асинхронно и не требует постоянного вычисления `scrollTop` / `offsetHeight`. Это делает его значительно эффективнее классического подхода через `window.addEventListener(‘scroll’, …)`.
