Гид по технологиям

Бесконечная прокрутка в Vue 3 — реализация с useInfiniteScroll

6 min read Vue Обновлено 26 Apr 2026
Бесконечная прокрутка в Vue 3 — useInfiniteScroll
Бесконечная прокрутка в Vue 3 — useInfiniteScroll

пользователь прокручивает ленту

Быстрая инструкция по реализации бесконечной прокрутки в Vue 3 с использованием @vueuse/core и JSONPlaceholder: создайте API-обёртку для получения данных, подключите useInfiniteScroll, отрисуйте список и проверьте производительность и доступность. В статье — готовые сниппеты, альтернативы и чек-листы для релиза.

Что такое бесконечная прокрутка

Бесконечная прокрутка — приём, когда приложение подгружает новые элементы по мере прокрутки страницы, вместо разбиения на пагинацию. Кратко: это удобный UX для длинных лент контента, но требует внимания к производительности, доступности и тестированию.

Краткое определение: бесконечная прокрутка динамически подгружает новые данные при достижении конца контейнера.

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

Основные подходы (умеренная модель)

  • useInfiniteScroll из @vueuse/core — готовое и простое решение для Vue 3.
  • IntersectionObserver + собственная логика — гибкость и контроль.
  • Виртуализация (vue-virtual-scroller) — для очень больших наборов данных.

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

Настройка приложения Vue

Чтобы выполнить примеры, требуется базовое понимание Vue 3, JavaScript и работы с HTTP (axios). Для начала создайте новое приложение Vue:

npm create vue  

При настройке проекта выберите No для всех дополнительных функций — в этом руководстве мы подключим только нужные пакеты вручную.

настройка приложения Vue

Перейдите в директорию приложения и установите пакеты:

npm install axios @iconify/vue @vueuse/core  

Установятся три пакета: axios (HTTP-запросы), @iconify/vue (иконки) и @vueuse/core (утилиты Vue, включая useInfiniteScroll).

Получение тестовых данных из JSONPlaceholder

Для примера мы используем публичный фейковый API JSONPlaceholder. В production вы будете работать с собственным API.

Создайте в src папку api и файл getComments.js со следующим кодом:

//getComments.js  
  
import axios from"axios";  
  
asyncfunctiongetComments(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);  
}  
}  
  
exportdefault getComments;  

Коротко: функция getComments(max, omit) делает GET-запрос и возвращает массив строк — тел комментариев.

Советы по API:

  • Всегда обрабатывайте ошибки и возвращайте понятный ответ на клиенте.
  • Подумайте о кэшировании и стратегиях повторных попыток (retry) для нестабильных сетей.

Создание компонента InfiniteScroll

Создайте src/components/InfiniteScroll.vue и добавьте скрипт-логику (оставляем код как есть):


  
  

Пояснения к коду:

  • listEl — ссылка на DOM-элемент, за которым следит useInfiniteScroll.
  • commentsDisplayed — сколько элементов загружаем за запрос (из примера 20).
  • commentsList загружается сразу при монтировании через await getComments(…).
  • commentsToDisplayOnScroll подгружает и добавляет новые элементы.
  • useInfiniteScroll принимает элемент, функцию-колбэк и опции (distance — расстояние в пикселях от конца, при котором запускается загрузка).

Важно: начальная загрузка через await в setup возможна благодаря в App.vue.

Шаблон компонента и использование

Добавьте шаблон для отображения списка:


  
  

Подключите компонент в App.vue:


  
  
  
  
  

Запустите приложение:

npm run dev

Превью приложения (при настройках из примера):

предпросмотр Vue приложения

Альтернативный подход: IntersectionObserver вручную

Когда нужен полный контроль над поведением (например, поддержка сложной логики загрузки), используйте IntersectionObserver вместо готовой утилиты.

Пример простого хука для Vue 3:

// useIntersectionLoad.js
import { ref, onMounted, onBeforeUnmount } from 'vue'

export function useIntersectionLoad(targetRef, callback, options = {}) {
  const observer = ref(null)

  onMounted(() => {
    if (!targetRef.value) return
    observer.value = new IntersectionObserver(async (entries) => {
      for (const entry of entries) {
        if (entry.isIntersecting) {
          await callback()
        }
      }
    }, options)
    observer.value.observe(targetRef.value)
  })

  onBeforeUnmount(() => {
    if (observer.value && targetRef.value) {
      observer.value.unobserve(targetRef.value)
    }
  })
}

Плюсы: гибкость, контроль над threshold и rootMargin. Минусы: чуть больше кода и ответственности за edge-cases.

Когда бесконечная прокрутка не подходит

  • Контенту нужна прямая нумерация страниц или конкретные URL для каждой позиции (SEO/поделиться ссылкой).
  • Пользователям важна возможность быстро перейти к концу списка.
  • Сильные требования к доступности без доп. усилий.

В этих случаях лучше использовать явную пагинацию или комбинированный подход “пагинация + подгрузка”.

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

  • Растущий DOM. Решение: виртуализация элементов (vue-virtual-scroller). При больших объёмах DOM-элементов виртуализация критична.
  • Частые ререндеры. Решение: мемоизация/ключи, минимизация реактивных зависимостей.
  • Сетевые задержки. Решение: кеширование, optimistic UI, prefetch следующей страницы.
  • Дублирующие запросы. Решение: блокировка повторных запросов (in-flight guard).

Рекомендации:

  • Параллельно загружайте не более одного запроса.
  • Используйте throttle/debounce для обработчиков прокрутки, когда не используете IntersectionObserver.
  • Сжимайте payload на сервере: отдавайте только нужные поля.

Доступность

  • Обеспечьте фокусируемую структуру и логичную последовательность чтения для экранных читалок.
  • Добавьте кнопку “Загрузить ещё” как альтернативный способ подгрузки — это полезно для пользователей клавиатуры и скринридеров.
  • Помечайте динамические контейнеры ARIA-ролями (role=”list” / role=”listitem”) при необходимости.
  • Обеспечьте возможность перейти к конкретному элементу (anchor links) или показать счётчик загруженных элементов.

Критерии приёмки

  • Компонент загружает первую порцию данных при старте.
  • При прокрутке до нижней границы контейнера подгружаются новые данные.
  • Повторная прокрутка не вызывает параллельных дублирующих запросов.
  • В случае ошибки отображается информативное сообщение и кнопка для повтора.
  • Тесты покрывают случаи: успешная загрузка, пустой результат, ошибка сети.

Чек-лист перед релизом

Для разработчика:

  • Обработаны ошибки запросов.
  • Есть индикаторы загрузки и fallback-контент.
  • Защита от повторных запросов (in-flight guard).
  • Тестовые сценарии написаны и проходят.

Для QA:

  • Протестирован сценарий низкой и высокой скорости сети.
  • Проведены тесты на мобильных устройствах.
  • Проверено поведение при пустом ответе API.

Для дизайнера:

  • Есть визуальный индикатор загрузки.
  • Есть альтернативный способ навигации (кнопка «Загрузить ещё»).

Для менеджера продукта:

  • Утверждён лимит на количество элементов за запрос.
  • Определена стратегия кэширования и TTL.

Тесты и сценарии приёма

  • Успешная первая загрузка: список содержит N элементов после монтирования.
  • Подгрузка после скролла: после прокрутки список увеличивается на N элементов.
  • Поведение при ошибке: показывается сообщение и кнопка «Повторить».
  • Кнопка «Загрузить ещё» работает как резервный механизм.

Шаблон быстрых настроек (cheat sheet)

  • Инициализация: commentsDisplayed = 20
  • Триггер загрузки: distance: 10 (px)
  • Защита от дублирования: isLoading flag
  • Адаптация под мобильные: уменьшить payload, lazy-load изображений

Типичные паттерны ошибок и как их исправлять

  • Дублирование элементов: используйте уникальные ключи и guard для in-flight запросов.
  • Неполная подгрузка: убедитесь, что вы правильно передаёте параметры start/limit.
  • Плохая производительность: включите виртуализацию и уменьшите количество DOM-узлов.

Мини‑методология внедрения

  1. Начните с простой реализации useInfiniteScroll и JSONPlaceholder.
  2. Протестируйте UX и измерьте рост DOM‑узлов.
  3. При необходимости добавьте виртуализацию.
  4. Добавьте кеширование и retry-логику.
  5. Покройте провальные сценарии тестами и QA.

Рекомендации по миграции с пагинации

  • Сохраняйте URL-идентификатор страницы в истории (history.pushState), если пользователям важно делиться ссылками.
  • Рассмотрите гибрид: пагинация на сервере + подгрузка на клиенте для UX, но с URL для навигации.

Конфиденциальность и обработка данных

  • Не подгружайте личные данные без явной необходимости.
  • Для персонализированного контента используйте защищённые эндпоинты и токены.
  • Сообщайте пользователю, если подгружается персонализированный контент.

Примеры альтернативных библиотек и инструментов

  • vue-virtual-scroller — для виртуализации больших списков.
  • react-virtualized / react-window — примеры для React, если мигрируете стек.
  • SWR / React Query / Vue Query — для управления кешем и состоянием загрузки.

Итоговая сводка

Бесконечная прокрутка в Vue 3 — удобная техника для лент контента. Для большинства задач достаточно @vueuse/core и useInfiniteScroll. При росте объёма данных учитывайте виртуализацию, защиту от дублирующих запросов и доступность. Тестируйте поведение на разных сетях и устройствах, добавляйте резервную кнопку «Загрузить ещё» для улучшения UX.

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

Спасибо за чтение — примените подход в своём проекте и протестируйте на реальных данных.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как разделить меш в Blender
3D моделирование

Как разделить меш в Blender

Как увеличить изображение без потери качества
Фото

Как увеличить изображение без потери качества

Как создать влог на iPhone — полное руководство
Видео

Как создать влог на iPhone — полное руководство

Как отразить экран на телевизор — все способы
Руководство

Как отразить экран на телевизор — все способы

Бесконечная прокрутка в Vue 3 — useInfiniteScroll
Vue

Бесконечная прокрутка в Vue 3 — useInfiniteScroll

Чёрный экран iPhone: как восстановить устройство
iPhone

Чёрный экран iPhone: как восстановить устройство