说明
本文主要是介绍一下 路由的后置守卫 afterEatch 的一个重要的作用 : 就是检测路由异常信息。
它的实现方式是 通过第三个参数来返回的。
而且,它的异常检测是全局的。
导航的异常有以下三种类型:
aborted
: 在导航守卫中 被拦截并返回了false;
cancelled
: 在导航完成之前又产生了一次新的导航;
duplicated
: 导航被阻止,已经在目标位置了。
下面通过案例来认识一下这三种异常。
补充1
vue-router 中提供了 关于路由导航异常的检测API :
isNavigationFailure()
: 判断路由是否是某种异常
NavigationFailureType
: 包含了上述三种异常状态的枚举。
补充2
我们在代码中通过
编程式导航
如push
方法进行路由时,
都会返回一个Promise
对象,
我们可以正常的订阅这个 Promise 对象,从而实现 在路由结束之后做一些逻辑处理。
aborted
在导航守卫中 被拦截并返回了false。
(1)在前置守卫中拦截/b
;
(2)在后置守卫中检测到aborted
异常信息。
路由配置如下
// 导入 定义路由的两个方法
import {createRouter,createWebHistory} from 'vue-router'
// 懒加载写法: 先声明,下面直接使用
const componentA = () => import('./componentA.vue')
const componentB = () => import('./componentB.vue')
// 声明路由跳转的路径与组件的对应关系
const routsList = [
// 直接使用上面声明的组件
{path:'/a',name:'aroute',component:componentA},
{path:'/b',name:'broute',component:componentB}
]
// 创建路由的实例对象
const routerConfigObj = createRouter({
history:createWebHistory('abc'), // 带一个参数,表示是路由的一个前缀
routes:routsList // 指定路由的配置列表
})
// 前置守卫
routerConfigObj.beforeEach((to,from)=>{
console.log('前置守卫 : to : ',to)
console.log('前置守卫 :from : ',from)
// 当路由地址是 /b 时 , 手动停止跳转,模拟跳转中止的情况
if(to.path == '/b'){
console.log('前置守卫 : 是 /b 路由,拦截它')
console.log('------')
// 直接返回 false
return false; // aborted
}
return true
})
// 后置守卫
routerConfigObj.afterEach((to,from,failureObj) => {
console.log('后置守卫 : to : ',to)
console.log('后置守卫 :from : ',from)
console.log('后置守卫 :failureObj : ',failureObj)
console.log('------')
})
// 导出路由的对象
export default routerConfigObj;
运行结果:
cancelled
在导航守卫中 被拦截 并且 重新导航到一个新的路由上去。
路由配置如下:
// 导入 定义路由的两个方法
import {createRouter,createWebHistory} from 'vue-router'
// 懒加载写法 : 先声明,下面直接使用
const componentA = () => import('./componentA.vue')
const componentB = () => import('./componentB.vue')
// 声明路由跳转的路径与组件的对应关系
const routsList = [
// 直接使用上面声明的组件
{path:'/a',name:'aroute',component:componentA},
{path:'/b',name:'broute',component:componentB}
]
// 创建路由的实例对象
const routerConfigObj = createRouter({
history:createWebHistory('abc'), // 带一个参数,表示是路由的一个前缀
routes:routsList // 指定路由的配置列表
})
// 前置守卫
routerConfigObj.beforeEach((to,from)=>{
console.log('前置守卫 : to : ',to)
console.log('前置守卫 :from : ',from)
// 当路由地址是 /b 时 , 手动停止跳转,模拟跳转中止的情况
if(to.path == '/b'){
console.log('前置守卫 : 是 /b 路由,拦截它,重新push到 /a 这个路由上去')
console.log('------')
// push 到新的路由中去
routerConfigObj.push('/a') // cancelled
}
return true
})
// 后置守卫
routerConfigObj.afterEach((to,from,failureObj) => {
console.log('后置守卫 : to : ',to)
console.log('后置守卫 :from : ',from)
console.log('后置守卫 :failureObj : ',failureObj)
console.log('------')
})
// 导出路由的对象
export default routerConfigObj;
运行结果
duplicated
路由重复跳转时会触发的异常。
例如 : 当前我们已经在/a
上面了,点击按钮,又想跳转到/a
上面,此时就会触发这个异常。
本案例就使用到了
补充1
和补充2
中的知识点了。
路由配置
// 导入 定义路由的两个方法
import {createRouter,createWebHistory} from 'vue-router'
// 懒加载写法 : 先声明,下面直接使用
const componentA = () => import('./componentA.vue')
// 声明路由跳转的路径与组件的对应关系
const routsList = [
// 直接使用上面声明的组件
{path:'/a',name:'aroute',component:componentA}
]
// 创建路由的实例对象
const routerConfigObj = createRouter({
history:createWebHistory('abc'), // 带一个参数,表示是路由的一个前缀
routes:routsList // 指定路由的配置列表
})
// 前置守卫
routerConfigObj.beforeEach((to,from)=>{
console.log('前置守卫 : to : ',to)
console.log('前置守卫 :from : ',from)
console.log('------')
})
// 后置守卫
routerConfigObj.afterEach((to,from,failureObj) => {
console.log('后置守卫 : to : ',to)
console.log('后置守卫 :from : ',from)
console.log('后置守卫 :failureObj : ',failureObj)
console.log('------')
})
// 导出路由的对象
export default routerConfigObj;
组件A 中的操作 : 有一个按钮,点击按钮,仍然跳转到当前的路由上
<template>
<div class="diva">
这是组件A
<br>
<button @click="goToA">跳转到组件A</button>
</div>
</template>
<script setup lang="ts">
// 引入两个路由相关的方法
import { useRouter,useRoute} from 'vue-router';
// 声明 路由实例对象 和 当前路由对象
const routerObj = useRouter()
const currentRoute = useRoute()
// 打印一下路由实例对象 和 当前路由对象
console.log('A 组件 中 路由实例对象 :',routerObj)
console.log('A 组件 中 当前路由对象 :',currentRoute)
// 导入 路由异常 相关的API
import { isNavigationFailure,NavigationFailureType} from 'vue-router';
// 跳转到自己
const goToA = () =>{
routerObj.push('/a')
.then((failure:any) => {
console.log('push 中的错误返回结果 :', failure)
if(isNavigationFailure(failure,NavigationFailureType.duplicated)){
console.log('路由重复了')
}else{
console.log('路由没有重复')
}
})
}
</script>
<style scoped>
.diva{
width: 300px;
height: 200px;
background: red;
}
</style>
运行结果