Сохранение позиции скролла

Vue Router предоставляет встроенные механизмы для управления поведением прокрутки при навигации между маршрутами. Веб-приложения с динамическим контентом часто требуют восстановления позиции скролла при возврате на предыдущую страницу или при переходе между секциями. Для этого используется опция scrollBehavior при создании экземпляра роутера.

Настройка scrollBehavior

Опция scrollBehavior принимает функцию с тремя параметрами: to, from и savedPosition. Она вызывается при каждой навигации и позволяет определить, куда прокрутить страницу. Стандартная сигнатура выглядит следующим образом:

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About },
  ],
  scrollBehavior(to, from, savedPosition) {
    if (savedPosition) {
      return savedPosition;
    } else {
      return { top: 0 };
    }
  },
});
  • savedPosition используется только при навигации назад или вперёд в истории браузера. Если она существует, возвращается объект с координатами { x, y }.
  • В остальных случаях можно задать прокрутку к верхней части страницы { top: 0 } или к конкретному элементу через селектор.

Прокрутка к элементу по селектору

Vue Router позволяет прокручивать страницу к элементу, используя CSS-селектор. Для этого возвращается объект вида { el: '#id', beh * avior: 'smooth' }:

scrollBehavior(to, from, savedPosition) {
  if (to.hash) {
    return {
      el: to.hash,
      beh * avior: 'smooth',
    };
  }
  return { top: 0 };
}
  • to.hash содержит значение якоря в URL, например #section1.
  • Свойство behavior может быть 'auto' (по умолчанию) или 'smooth' для плавной прокрутки.

Асинхронная прокрутка

Функция scrollBehavior может быть асинхронной, возвращая Promise. Это полезно, если элементы загружаются динамически и необходимо дождаться их появления на странице перед прокруткой:

scrollBehavior(to, from, savedPosition) {
  return new Promise((resolve) => {
    setTimeout(() => {
      if (to.hash) {
        resolve({ el: to.hash });
      } else {
        resolve({ top: 0 });
      }
    }, 300);
  });
}

Такой подход гарантирует корректное позиционирование даже при ленивой загрузке компонентов или контента.

Учет вложенных маршрутов

При использовании вложенных маршрутов важно учитывать, что scrollBehavior вызывается один раз за полную навигацию. Если на странице несколько <router-view>, можно реализовать индивидуальное поведение для каждого уровня маршрута, проверяя to.matched:

scrollBehavior(to, from, savedPosition) {
  if (savedPosition) {
    return savedPosition;
  }
  const deepestRoute = to.matched[to.matched.length - 1];
  if (deepestRoute.meta.scrollToTop === false) {
    return false;
  }
  return { top: 0 };
}
  • to.matched — массив совпавших маршрутов от родительского до вложенного.
  • Использование meta позволяет настраивать прокрутку на уровне отдельных маршрутов.

Советы по оптимизации UX

  • Всегда возвращать savedPosition при навигации назад/вперед, чтобы сохранить привычное поведение браузера.
  • Для длинных страниц с якорями стоит использовать плавную прокрутку через beh * avior: 'smooth'.
  • Если на странице есть ленивые компоненты, лучше делать прокрутку асинхронно, чтобы избежать сдвигов и перескакиваний контента.
  • Можно комбинировать прокрутку к якорям и к верхней части страницы в зависимости от маршрута, используя условные проверки to.hash и meta свойства маршрута.

Пример комплексного scrollBehavior

scrollBehavior(to, from, savedPosition) {
  if (savedPosition) {
    return savedPosition;
  }
  if (to.hash) {
    return { el: to.hash, beh * avior: 'smooth' };
  }
  if (to.meta.scrollToTop === false) {
    return false;
  }
  return { top: 0 };
}

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