Vue3-39-路由-导航异常的检测 afterEatch 与 编程式导航之后的订阅动作

news/2025/2/12 18:13:15/

说明

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

运行结果

在这里插入图片描述


http://www.ppmy.cn/news/1297891.html

相关文章

【实用工具指南 三】CHAT-GPT4接入指南

好消息&#xff0c;CHAT-GPT4终于开放订阅了&#xff0c;聪明的人已经先用上了&#xff0c;先上个图。 但是去订阅的时候发现银行卡验证不通过&#xff0c;后来一查必须是老美的州才行&#xff0c;于是买了个美元虚拟卡 接下来就比较简单&#xff0c;直接找客服把GPT的充值界…

并发程序设计--D11D12进程间通信

概念&#xff1a;就是进程和进程之间交换信息。 常用通信方式 无名管道&#xff08;pipe&#xff09; 有名管道 &#xff08;fifo&#xff09; 信号&#xff08;signal&#xff09; 共享内存映射(mmap) 套接字&#xff08;socket&#xff09; 过时的IPC通信方式 System…

Influxdb2修改管理员密码

通过恢复管理员令牌来重置InfluxDB2管理员的密码 1.找到数据库的配置文件 一般为config.json 2.配置文件的的blod文件配置 3.在这个混合文本和二进制json文件中搜索已知的用户名或token之类的字符串。 例如&#xff1a; "id":"0bd73badf2941000","…

最新最简操作系统期末复习(考前速过)

操作系统复习 第一章&#xff08;操作系统引论&#xff09;计算机操作系统包括&#xff1a;操作系统的目标&#xff1a;操作系统的作用&#xff1a;未配置操作系统的计算机系统&#xff1a;单道批处理系统&#xff1a;缺点&#xff1a; 多道批处理系统&#xff1a;优点&#xf…

【案例实战】业务稳定性运行之全链路混合压测

1.全链路压测开展步骤 &#xff08;1&#xff09;什么是全链路压测 全链路压测是指基于真实业务场景&#xff0c;通过模拟海量的用户请求&#xff0c;对整个后台服务进行压力测试&#xff0c;从而评估整个系统的性能水平。 对应用程序的整个技术栈进行完整的压力和性能测试&a…

uni-app使用uni-ui加ts类型限制

uni-app使用uni-ui加ts类型限制 安装 uni-ui 组件库 pnpm i dcloudio/uni-ui配置自动导入组件 // pages.json {// 组件自动导入"easycom": {"autoscan": true,"custom": {// uni-ui 规则如下配置 "^uni-(.*)": "dcloudio/uni…

C++力扣题目-- 二叉树层序遍历

102.二叉树的层序遍历(opens new window)107.二叉树的层次遍历II(opens new window)199.二叉树的右视图(opens new window)637.二叉树的层平均值(opens new window)429.N叉树的层序遍历(opens new window)515.在每个树行中找最大值(opens new window)116.填充每个节点的下一个右…

C++ 具名要求-全库范围的概念 - (Swappable) - (ValueSwappable)

此页面中列出的具名要求&#xff0c;是 C 标准的规范性文本中使用的具名要求&#xff0c;用于定义标准库的期待。 某些具名要求在 C20 中正在以概念语言特性进行形式化。在那之前&#xff0c;确保以满足这些要求的模板实参实例化标准库模板是程序员的重担。若不这么做&#xf…