等待导航结果
使用 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
}