# Навигационные хуки
Как следует из названия, навигационные хуки vue-router
используются для перенаправлений или отмены навигационных переходов. Есть несколько способов внедрить навигационный хук: глобально, для конкретного маршрута, или для конкретного компонента.
Следует помнить, что изменение параметров маршрута не вызывает выполнения навигационных хуков enter/leave. Вы можете добавить watch на объект $route
для отслеживания этих изменений, или использовать хук beforeRouteUpdate
.
# Глобальные хуки (до навигационных хуков)
Глобальный хук можно зарегистрировать через router.beforeEach
:
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
Глобальные навигационные хуки вызываются в порядке их создания при каждом навигационном переходе. Допускается асинхронное разрешение хуков — в этом случае переход считается незавершённым до тех пор, пока не будут разрешены все хуки.
В каждый навигационный хук передаётся три параметра:
to: Route
: целевой объект Route, к которому осуществляется переход.from: Route
: текущий маршрут, с которого осуществляется переход к новому.next: Function
: функция, вызов которой разрешает хук. В зависимости от переданных вnext
аргументов, результатом будет:next()
: переход к следующему хуку в цепочке. Если хуков больше нет, переход считается подтверждённым.next(false)
: отмена перехода. Если URL был изменён (вручную пользователем, или кнопкой "назад"), он будет сброшен на соответствующий маршрутfrom
.next('/')
илиnext({ path: '/' })
: перенаправление на другой маршрут. Текущий переход будет отменён, и процесс начнётся заново для нового маршрута. Вы можете передать любой объект местоположения вnext
, который позволяет вам указывать опции такие какreplace: true
,name: 'home'
и любой другой параметр используемый во входном параметреto
компонентаrouter-link
илиrouter.push
next(error)
: (добавлено в версии 2.4.0+) если аргумент, переданныйnext
является экземпляромError
, навигация будет прервана и ошибка будет передана в коллбэк, зарегистрированный черезrouter.onError()
.
Убедитесь, что функция next
будет вызываться в навигационном хуке только 1 раз в любом случае. Вызовы могут встречаться несколько раз, но важно чтобы они не пересекались логически, иначе хук никогда не разрешится или выдаст ошибки. Вот пример перенаправления пользователя на страницу /login
если он не авторизован:
// ПЛОХО
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
// если пользователь не авторизован, то `next` будет вызываться дважды
next()
})
// ХОРОШО
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
# Глобальные хуки разрешения перехода
Вы можете зарегистрировать глобальный хук с помощью router.beforeResolve
. Это похоже на router.beforeEach
, с той разницей, что разрешающий хук будет вызван непосредственно перед подтверждением навигации, после того, как будут разрешены все хуки компонента и асинхронные компоненты для маршрута.
# Глобальные хуки завершения перехода
Можно также зарегистрировать глобальные хуки, вызываемые после завершения перехода. Однако, в отличие от сторожевых хуков, в них не передаётся функция next
, и на навигацию они повлиять не могут:
router.afterEach((to, from) => {
// ...
})
# Хуки для конкретных маршрутов
Навигационные хуки beforeEnter
можно указать напрямую для конкретного маршрута в его конфигурации:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
Эти хуки имеют точно такую же сигнатуру, как и глобальные хуки.
# Хуки для конкретных компонентов
Наконец, навигационный хук можно указать и непосредственно в компоненте (том, что указан в конфигурации маршрута), используя следующие опции:
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
const Foo = {
template: `...`,
beforeRouteEnter(to, from, next) {
// вызывается до подтверждения пути, соответствующего этому компоненту.
// НЕ ИМЕЕТ доступа к контексту экземпляра компонента `this`,
// так как к моменту вызова экземпляр ещё не создан!
},
beforeRouteUpdate(to, from, next) {
// вызывается когда маршрут, что рендерит этот компонент изменился,
// но этот компонент будет повторно использован в новом маршруте.
// Например, для маршрута с динамическими параметрами `/foo/:id`, когда мы
// перемещаемся между `/foo/1` и `/foo/2`, экземпляр того же компонента `Foo`
// будет использован повторно, и этот хук будет вызван когда это случится.
// Также имеется доступ в `this` к экземпляру компонента.
},
beforeRouteLeave(to, from, next) {
// вызывается перед переходом от пути, соответствующего текущему компоненту;
// имеет доступ к контексту экземпляра компонента `this`.
}
}
Хук beforeRouteEnter
НЕ ИМЕЕТ доступа к this
, так как к моменту его вызова навигация ещё не подтверждена, а значит и экземпляр компонента ещё не создан.
Тем не менее, доступ к экземпляру можно получить, передав коллбэк в next
. Эта функция будет вызвана после подтверждения навигации, а экземпляр компонента будет передан в неё в качестве параметра:
beforeRouteEnter(to, from, next) {
next(vm => {
// экземпляр компонента доступен как `vm`
})
}
Обратите внимание, что beforeRouteEnter
— единственный хук, который поддерживает передачу коллбэка в next
. Для beforeRouteUpdate
и beforeRouteLeave
, this
уже доступен, поэтому передача коллбэка не требуется и поэтому не поддерживается:
beforeRouteUpdate(to, from, next) {
// просто используйте `this`
this.name = to.params.name
next()
}
Навигационный хук ухода со страницы обычно используется для предотвращения случайного ухода пользователя со страницы с несохранёнными изменениями. Навигацию можно отменить вызовом next(false)
.
beforeRouteLeave(to, from, next) {
const answer = window.confirm('Вы хотите уйти? У вас есть несохранённые изменения!')
if (answer) {
next()
} else {
next(false)
}
}
При использовании примесей, которые будут добавлять навигационные хуки для компонента, убедитесь, что объявляете примесь после установки плагина vue-router:
Vue.use(Router)
Vue.mixin({
beforeRouteUpdate(to, from, next) {
// ...
}
})
# Полная цепочка обработки навигации
- Срабатывание навигации.
- Вызов
beforeRouteLeave
хуков в деактивируемых компонентах. - Вызов глобальных
beforeEach
хуков. - Вызов
beforeRouteUpdate
хука в переиспользуемых компонентах. - Вызов
beforeEnter
в конфигурации маршрута. - Разрешение асинхронных компонентов для маршрута.
- Вызов
beforeRouteEnter
в активируемых компонентах. - Вызов глобальных
beforeResolve
хуков. - Навигация подтверждена.
- Вызов глобальных
afterEach
хуков. - Выполняется обновление DOM.
- Вызов коллбэков, переданных в
next
вbeforeRouteEnter
хуке с созданными экземплярами.