Skip to content
Перевод синхронизирован с документацией от , хэш коммита 960662d.

Ожидание результата навигации

При использовании router-link, Vue Router вызывает router.push для запуска навигации. В то время как ожидаемое поведение для большинства ссылок - перевести пользователя на новую страницу, есть несколько ситуаций, когда пользователь останется на той же странице:

  • Пользователь уже находится на странице, на которую пытается перейти.
  • Навигационный хук прерывает навигацию, вызывая return false.
  • Запускается новый навигационный хук, пока предыдущий еще не закончен.
  • Навигационный хук перенаправляет в другое место, возвращая новый путь (например, return '/login').
  • Навигационный хук выбрасывает Error.

Если мы хотим сделать что-то после завершения перехода навигации, то нам нужен способ подождать после вызова router.push. Представьте, что у нас есть мобильное меню, позволяющее переходить на разные страницы, и мы хотим скрыть меню только после перехода на новую страницу. Мы можем сделать примерно следующее:

js
router.push('/my-profile')
this.isMenuOpen = false

Но это сразу же закроет меню, поскольку переходы навигации являются асинхронными, нам нужно дождаться разрешения Promise, возвращаемого router.push:

js
await router.push('/my-profile')
this.isMenuOpen = false

Теперь меню будет закрываться по завершению перехода навигации, но оно также закроется, если навигация была предотвращена. Нам нужен способ определить, действительно ли мы изменили страницу, на которой находимся, или нет.

Определение сбоев при навигации

Если навигация была предотвращена, в результате чего пользователь остался на той же странице, то разрешенным значением Promise, возвращаемым router.push, будет сбой навигации (Navigation Failure). В противном случае это будет falsy значение (обычно undefined). Это позволяет определить статус перехода навигации:

js
const navigationResult = await router.push('/my-profile')

if (navigationResult) {
  // навигация предотвращена
} else {
  // навигация прошла успешно (в том числе и в случае переадресации)
  this.isMenuOpen = false
}

Сбои навигации представляют собой экземпляры Error с несколькими дополнительными свойствами, которые предоставляют достаточно информации, чтобы понять, какая навигация была предотвращена и почему. Чтобы проверить характер результата навигации, используйте функцию isNavigationFailure:

js
import { NavigationFailureType, isNavigationFailure } from 'vue-router'

// попытка покинуть страницу редактирования статьи без сохранения
const failure = await router.push('/articles/2')

if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
  // показать пользователю небольшое уведомление
  showToast('You have unsaved changes, discard and leave anyway?')
}

Совет

Если опустить второй параметр: isNavigationFailure(failure), то будет проверяться только то, является ли failure сбоем навигации.

Обнаружить сбои навигации на уровне приложения можно с помощью навигационного хука router.afterEach():

ts
router.afterEach((to, from, failure) => {
  if (failure) {
    sendToAnalytics(to, from, failure)
  }
})

Типы сбоев навигации

Как мы сказали в начале, существуют разные ситуации, при которых отменяется навигация, и все они приводят к разным сбоям навигации. Их можно различить с помощью isNavigationFailure и NavigationFailureType. Существует три разных типа:

  • aborted: когда внутри навигационного хука вернулось false
  • cancelled: Запущена новая навигация до завершения текущей. Например, был вызван router.push был вызван во время ожидания внутри навигационного хука.
  • duplicated: Навигация была предотвращена, так как мы на этой странице.

Все сбои навигации предоставляют доступ к свойствам to и from, отражающие текущее местоположение, а также целевое местоположение для неудавшейся навигации:

js
// попытка доступа к странице администратора
router.push('/admin').then(failure => {
  if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
    failure.to.path // '/admin'
    failure.from.path // '/'
  }
})

Во всех случаях значения to и from будут объектами нормализованных маршрутов.

Обнаружение перенаправлений

При возвращении нового маршрута внутри навигационного хука, мы запускаем новый переход навигации, который перезаписывает текущий. В отличие от других возвращаемых значений, перенаправление не предотвращает навигацию, оно создает новую. Поэтому оно проверяется по-разному, через свойство redirectedFrom в Route Location:

js
await router.push('/my-profile')
if (router.currentRoute.value.redirectedFrom) {
  // redirectedFrom - это разрешенное местоположение маршрута, как to и from в навигационных хуках
}

Released under the MIT License.