说明
本文主要是介绍一下 路由的后置守卫 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>
运行结果