Scroll behavior
↑ 5.1 Vue Router · ← Предыдущая
Зачем это на собесе
Небольшая, но заметная UX-деталь: сохранение позиции при «назад» и прокрутка к якорям.
Объяснение
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) return savedPosition; // «назад/вперёд» — вернуть позицию
if (to.hash) return { el: to.hash, behavior: "smooth", top: 80 }; // якорь с отступом под шапку
if (to.path === from.path) return false; // смена query — не прокручивать
return { top: 0 }; // новая страница — вверх
},
});
// Ожидание рендера/загрузки данных перед прокруткой
scrollBehavior: () => new Promise((resolve) => setTimeout(() => resolve({ top: 0 }), 300)),Особенности:
- Работает только в режимах history (не в hash без History API).
- Возвращаемое значение: координаты
{ top, left },{ el, top },savedPositionилиfalse. - Может быть асинхронным: дождитесь появления контента (
await nextTick()), иначе прокрутка произойдёт до отрисовки. - Прокрутка внутри вложенных контейнеров (не
window) роутер не выполняет — управляйте вручную (watch(route)иel.scrollTo). - Сохранение позиции для длинных списков с ленивой загрузкой: восстановите после загрузки данных, либо кэшируйте страницу через
KeepAlive.
Доступность: при переходе в SPA фокус остаётся на прошлом элементе — переносите фокус на заголовок страницы (h1) и объявляйте смену страницы (aria-live), чтобы скринридеры понимали навигацию.
router.afterEach(async () => { await nextTick(); document.querySelector<HTMLElement>("h1")?.focus(); });Нюансы и подводные камни
- Данные загружаются позже DOM — сохранённая позиция может не восстановиться.
- Якорные ссылки не работают, если элемента ещё нет.
- Фиксированная шапка перекрывает целевой элемент — добавляйте
topиscroll-margin-top. - Использование
overflowконтейнера вместоwindowломает стандартную логику.
Практика
- Настройте
scrollBehaviorс якорями и «назад». - Перенесите фокус на заголовок после навигации.
- Восстановите позицию длинного списка после возврата.
Вопросы с ответами
Как сохранить позицию прокрутки при возврате?
Использовать
savedPositionвscrollBehavior(с ожиданием отрисовки данных).
Что происходит с фокусом при SPA-навигации?
Остаётся на прошлом элементе; для доступности его переносят на заголовок новой страницы.