Состояние истории (history state)

Vue Router предоставляет мощный механизм для управления состоянием истории браузера, позволяя создавать маршрутизацию в стиле одностраничных приложений с полным контролем над навигацией. Основной объект, отвечающий за состояние истории, — это History API, встроенный в браузеры. Vue Router поверх этого API реализует несколько стратегий навигации, наиболее часто используемые из которых — HTML5 history mode и hash mode.

HTML5 History Mode

При использовании HTML5 history mode навигация осуществляется через методы pushState и replaceState объекта window.history. Эти методы позволяют изменять URL без перезагрузки страницы, сохраняя при этом состояние текущего маршрута.

  • pushState(state, title, url) — добавляет новый элемент в стек истории. Параметры:

    • state — объект, который будет храниться вместе с этим элементом истории. Этот объект доступен при навигации через history.state.
    • title — название документа (часто используется пустая строка, так как большинство браузеров игнорируют этот параметр).
    • url — новый адрес, который будет отображаться в адресной строке браузера.
  • replaceState(state, title, url) — заменяет текущий элемент в стеке истории без добавления нового. Используется для обновления состояния маршрута без увеличения длины истории.

В Vue Router эти методы используются автоматически при вызове методов $router.push() и $router.replace(), если активирован history mode. Например:

import { createRouter, createWebHistory } from 'vue-router'

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

// Добавление нового маршрута в историю
router.push('/about')

// Замена текущего маршрута
router.replace({ path: '/' })

Hash Mode

Hash mode основан на использовании символа # в URL. Каждый маршрут после символа # не отправляется на сервер, что позволяет реализовать навигацию без использования History API. В этом режиме состояние маршрута хранится в хэше, а не в объекте history.state.

import { createRouter, createWebHashHistory } from 'vue-router'

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

router.push('/about') // URL: example.com/#/about

Hash mode подходит для приложений, где сервер не поддерживает перезапись URL или не настроен на корректную отдачу маршрутов HTML5.

Объект state и его применение

Каждое изменение маршрута в history mode может сопровождаться объектом state. Этот объект позволяет хранить произвольные данные, которые будут доступны при навигации “назад” и “вперед”.

Пример:

router.push({
  path: '/profile',
  state: { userId: 42 }
})

// Получение состояния при навигации
window.addEventListener('popstate', (event) => {
  console.log(event.state) // { userId: 42 }
})

Ключевые моменты использования state:

  • Объект state сохраняется только в браузере и не виден в адресной строке.
  • Позволяет хранить информацию, которая не должна быть частью URL, например фильтры, позицию скролла, данные формы.
  • При переходе на предыдущий или следующий маршрут браузер автоматически возвращает сохранённое состояние через событие popstate.

Управление навигацией через состояние

Vue Router обеспечивает удобные методы для работы с состоянием истории без прямого обращения к window.history:

  • $router.push(location, onComplete?, onAbort?) — добавляет новый маршрут в историю.
  • $router.replace(location, onComplete?, onAbort?) — заменяет текущий маршрут.
  • $router.go(n) — перемещается по истории на n шагов (отрицательное значение — назад, положительное — вперёд).
// Перемещение на один шаг назад
router.go(-1)

// Перемещение на два шага вперёд
router.go(2)

События навигации и history.state

Для отслеживания изменений состояния истории можно использовать глобальные хуки навигации:

  • beforeEach(to, from, next) — вызывается перед каждой навигацией.
  • afterEach(to, from) — вызывается после завершения навигации.

С помощью этих хуков можно синхронизировать состояние приложения с history.state, например для сохранения состояния компонентов или управления кэшем страниц.

router.beforeEach((to, from, next) => {
  if (to.state?.scrollPosition) {
    window.scrollTo(0, to.state.scrollPosition)
  }
  next()
})

Особенности и ограничения

  • История браузера имеет ограниченный размер для объектов state. Обычно это несколько мегабайт, но хранить большие объекты не рекомендуется.
  • При обновлении страницы объект state сохраняется, но не сериализуется в URL.
  • При переходе между разными доменами объект state теряется.

Использование history state совместно с Vue Router позволяет реализовать сложные сценарии навигации, включая хранение временного состояния компонентов, управление формами и интерактивными интерфейсами без изменения URL. Такой подход обеспечивает высокую отзывчивость и удобство работы с одностраничными приложениями.