Бесконечная прокрутка в Vue 3: как реализовать

Бесконечная прокрутка (infinite scroll) — приём, при котором приложение подгружает контент по мере прокрутки. Это избавляет пользователя от нумерованных страниц и подходит для лент, комментариев и медиа-потоков.
Определение: useInfiniteScroll — утилита из @vueuse/core, которая отслеживает элемент и вызывает функцию, когда пользователь приближается к концу списка.
Что понадобится
- Базовые знания Vue 3 и JavaScript.
- Умение делать HTTP‑запросы (в примерах используется axios).
- Node.js и npm.
Важно: примеры используют бесплатный тестовый API JSONPlaceholder. В реальном проекте ваш API может работать иначе (аутентификация, страницы, лимиты).
Создание проекта Vue
Запустите команду в папке, где хотите создать проект:
npm create vueПри настройке выберите «No» для дополнительных опций — в этом руководстве мы не добавляем фреймворки или роутинг.
Перейдите в папку проекта и установите нужные пакеты:
npm install axios @iconify/vue @vueuse/coreКоротко о пакетах:
- axios — HTTP‑клиент.
- @iconify/vue — компонент для иконок.
- @vueuse/core — набор полезных хуков; в том числе useInfiniteScroll.
Получение тестовых данных из JSONPlaceholder
Чтобы имитировать реальный поток данных, используем API JSONPlaceholder и создадим утилиту для получения комментариев.
Создайте папку src/api и файл src/api/getComments.js со следующим кодом:
// src/api/getComments.js
import axios from "axios";
async function getComments(max, omit) {
try {
const comments = await axios.get(
`https://jsonplaceholder.typicode.com/comments?_limit=${max}&_start=${omit}`
);
return comments.data.map((comment) => comment.body);
} catch (error) {
console.error(error);
return [];
}
}
export default getComments;Пояснения:
- Параметр max управляет количеством элементов в одном запросе.
- Параметр omit (offset) говорит, с какого места начинать выборку.
- Функция возвращает массив строк с телами комментариев.
Важно: в рабочем приложении обрабатывайте ошибки и коды ответа сервера более детально.
Компонент InfiniteScroll — логика
Создайте файл src/components/InfiniteScroll.vue. В script‑блоке опишем логику загрузки и подключим useInfiniteScroll.
Ключевые моменты:
- listEl — ссылка на DOM‑элемент, в сторону которого слушает useInfiniteScroll.
- pageSize — размеры страницы; можно конфигурировать.
- loading и allLoaded помогают избежать дублирующих вызовов и понимать, когда данных больше нет.
Компонент InfiniteScroll — шаблон
Добавьте шаблон в тот же файл для рендеринга списка и индикатора загрузки.
-
{{ comment }}
Загрузка...
Больше нет данных
Важно: добавьте уникальные ключи для v-for при работе с реальными сущностями (например, comment.id).
Использование в App.vue
Импортируйте компонент и оберните его в Suspense, чтобы показать fallback во время первоначальной загрузки.
Запустите проект командой:
npm run devНа экране вы увидите начальную порцию комментариев. При прокрутке вниз будут подгружаться следующие партии.
Дизайн и хорошая практика
- Показывайте индикатор загрузки.
- Обрабатывайте конец данных (сообщение «Больше нет данных»).
- Дедупликация: сервер может возвращать дубли — фильтруйте на клиенте.
- Ограничьте параллельные запросы (флаг loading).
- Поддержите повторную попытку при ошибке.
Важно: протестируйте на мобильных устройствах — поведение скролла может отличаться.
Когда бесконечная прокрутка плохо работает
- SEO: поисковые роботы могут не индексировать контент, который подгружается динамически. Для публичных страниц лучше использовать пагинацию или серверный рендеринг.
- Пользователь теряет контекст: долго прокручивая, сложно вернуться к ранее увиденному месту.
- Производительность: тысячи DOM‑узлов замедляют страницу. Используйте виртуализацию для длинных списков.
- Доступность: клавиатурная навигация и скринридеры хуже работают с бесконечными лентами.
Альтернативные подходы
- Классическая пагинация (страницы) — лучше для SEO и для чёткой навигации.
- Кнопка “Загрузить ещё” — комбинация, дающая пользователю контроль над загрузкой.
- Виртуализация (windowing) с библиотеками вроде vue-virtual-scroller — отображает в DOM только видимые элементы.
Когда выбирать:
- Если важен SEO — пагинация или SSR.
- Если важно удержание в приложении (ленты соцсетей) — бесконечная прокрутка.
- Если список очень длинный — сочетание виртуализации и ленивой загрузки.
Модель принятия решения (коротко)
- UX важнее SEO → бесконечная прокрутка или кнопка “Загрузить ещё”.
- SEO важнее UX → пагинация или серверный рендеринг.
- Производительность критична → виртуализация.
Контрольный список для внедрения
- Обработаны ошибки сетевых запросов.
- Есть индикатор загрузки и сообщение об окончании данных.
- Предотвращено повторное выполнение параллельных запросов.
- Есть уникальные ключи для элементов списка.
- Протестировано на мобильных и настольных браузерах.
- Проверена доступность (tab order, aria‑атрибуты).
Критерии приёмки
- При открытии страницы загружается первая партия данных.
- При прокрутке к концу автоматически подгружается следующая партия.
- Повторных параллельных запросов не происходит.
- При отсутствии новых данных показывается сообщение «Больше нет данных».
- Приложение корректно отображает ошибку при отказе API и позволяет повторить попытку.
Отладочный план действий
- Откройте DevTools → Network и проверьте, когда отправляются запросы.
- Убедитесь, что offset/skip передается корректно.
- Проверьте флаги loading и allLoaded в компоненте.
- Проверьте, что все элементы в массиве имеют уникальные ключи (key).
- Если данные повторяются — добавьте фильтр по уникальному id.
Тесты и критерии приёмки (минимум)
- Unit: функция getComments корректно парсит ответ API.
- Интеграция: при клике/скролле увеличивается длина commentsList.
- E2E: реальное поведение прокрутки и загрузки в браузере.
Доступность и SEO
- Для читателей скринридеров добавьте aria‑метки и роли (например, role=”list” и role=”listitem”).
- Для улучшения SEO рассмотрите возможность сервера отдавать начальные страницы контента (SSR) или отдавать стандартные URL с пагинацией.
Безопасность и приватность
- Не логируйте персональные данные в консоль для продакшен‑окружения.
- Ограничьте число запросов к внешним API (rate limiting) и используйте кеширование.
- Для данных пользователя соблюдайте требования законодательства о персональных данных (например, GDPR) — при необходимости запрашивайте согласие.
Совместимость и миграция
- Проверяйте совместимость версий Vue и @vueuse/core перед обновлением.
- Если проект использует Vue 2, перенос логики потребует адаптации и других инструментов.
Шаблон конфигурации параметров (советы)
- pageSize: 10–50 — меньше для тяжёлого контента (изображения, видео), больше для короткого текста.
- distance: 10–100 px — срабатывание немного выше конца списка, чтобы подгрузка не задерживалась.
- retryPolicy: простая экспоненциальная повторная попытка при ошибках сети.
Примеры, когда это не подходит
- Страницы каталога товаров где нужен точный URL для каждой страницы.
- Электронные таблицы с важной нумерацией строк.
- Документы, где пользователь должен возвращаться к определённому месту по закладке.
Краткое руководство по внедрению (SOP)
- Добавьте утилиту получения данных (getComments или аналог).
- Создайте состояние: список, флаги loading и allLoaded.
- Реализуйте загрузку начальной партии в onMounted.
- Подключите useInfiniteScroll к контейнеру списка.
- Обработайте ошибки и граничные состояния.
- Тестируйте на разных устройствах и браузерах.
Социальная превью и объявление
OG заголовок: Бесконечная прокрутка в Vue 3 — быстрое руководство Краткое описание для твита: Реализуйте бесконечную ленту в Vue 3 с axios и useInfiniteScroll. Пошаговый пример, отладка и альтернативы.
Короткое объявление (для рассылки, 100–200 слов):
Изучите, как добавить бесконечную прокрутку в ваше Vue 3 приложение. В руководстве показано, как получать данные из JSONPlaceholder, как связать useInfiniteScroll из @vueuse/core с компонентом и как обеспечить корректную обработку ошибок и конца данных. Включены контрольные списки, критерии приёмки и альтернативные подходы для SEO и производительности.
Итоги
- Бесконечная прокрутка удобна для лент и потоков контента.
- Для реализации в Vue 3 удобно использовать axios и useInfiniteScroll из @vueuse/core.
- Учитывайте SEO, доступность и производительность; при необходимости выбирайте пагинацию или виртуализацию.
Спасибо за прочтение. Если нужно, могу подготовить вариант с виртуализацией (vue-virtual-scroller) или показать, как добавить серверный рендеринг для лучшей индексации.
Похожие материалы
Вторая временная зона в Google Календаре
Как изменить первый день недели в Google Календаре
Отключить события из Gmail в Google Календаре
Включить тёмный режим в Google Календаре
Тайм‑блокинг коммуникаций для продуктивной работы