等待导航结果
使用 router-link
时,Vue Router 会调用 router.push
来触发导航。虽然大多数链接的预期行为是将用户导航到新页面,但有一些情况会导致用户停留在同一页面
- 用户已经位于他们试图导航到的页面。
- 一个 导航守卫 通过执行
return false
来中止导航。 - 一个新的导航守卫在之前的导航守卫未完成时发生。
- 一个 导航守卫 通过返回一个新的位置来重定向到其他地方(例如
return '/login'
)。 - 一个 导航守卫 抛出一个
Error
。
如果我们想在导航完成后做一些事情,我们需要一种在调用 router.push
后等待的方法。想象一下,我们有一个移动菜单,它允许我们转到不同的页面,我们只想在导航到新页面后隐藏菜单,我们可能想要做这样的事情
router.push('/my-profile')
this.isMenuOpen = false
但这会立即关闭菜单,因为 导航是异步的,我们需要 await
router.push
返回的 Promise
await router.push('/my-profile')
this.isMenuOpen = false
现在菜单将在导航完成后关闭,但如果导航被阻止,它也会关闭。我们需要一种方法来检测我们是否真的从当前页面导航走了。
检测导航失败
如果导航被阻止,导致用户停留在同一页面,则 router.push
返回的 Promise
的解析值将是一个 导航失败。否则,它将是一个 假值(通常是 undefined
)。这使我们能够区分我们是否从当前页面导航走了
const navigationResult = await router.push('/my-profile')
if (navigationResult) {
// navigation prevented
} else {
// navigation succeeded (this includes the case of a redirection)
this.isMenuOpen = false
}
导航失败 是 Error
实例,它具有几个额外的属性,这些属性提供了足够的信息来了解哪些导航被阻止以及原因。要检查导航结果的性质,请使用 isNavigationFailure
函数
import { NavigationFailureType, isNavigationFailure } from 'vue-router'
// trying to leave the editing page of an article without saving
const failure = await router.push('/articles/2')
if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
// show a small notification to the user
showToast('You have unsaved changes, discard and leave anyway?')
}
提示
如果你省略第二个参数:isNavigationFailure(failure)
,它只会检查 failure
是否是一个 导航失败。
全局导航失败
你可以通过使用 router.afterEach()
导航守卫 来全局检测全局导航失败
router.afterEach((to, from, failure) => {
if (failure) {
sendToAnalytics(to, from, failure)
}
})
区分导航失败
正如我们在一开始所说,有不同的情况会导致导航中止,所有这些情况都会导致不同的 导航失败。它们可以使用 isNavigationFailure
和 NavigationFailureType
来区分。有三种不同的类型
aborted
:在导航守卫中返回false
来阻止导航。cancelled
:在当前导航完成之前发生了新的导航。例如,在导航守卫中等待时调用了router.push
。duplicated
:导航被阻止,因为我们已经位于目标位置。
导航失败 的属性
所有导航失败都公开 to
和 from
属性,以反映当前位置以及失败导航的目标位置
// trying to access the admin page
router.push('/admin').then(failure => {
if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
failure.to.path // '/admin'
failure.from.path // '/'
}
})
在所有情况下,to
和 from
都是规范化的路由位置。
检测重定向
在导航守卫中返回一个新的位置时,我们会触发一个新的导航,它会覆盖正在进行的导航。与其他返回值不同,重定向不会阻止导航,它会创建一个新的导航。因此,它通过读取路由位置中的 redirectedFrom
属性来进行不同的检查
await router.push('/my-profile')
if (router.currentRoute.value.redirectedFrom) {
// redirectedFrom is resolved route location like to and from in navigation guards
}