【Vue实战】Vuex 和 Axios 拦截器设置全局 Loading

目录

1. 效果图

 2. 思路分析

 2.1 实现思路

2.2 可能存在的问题

2.2.1 并发请求管理

2.2.2 请求快速响应和缓存带来的问题

3. 代码实现

4. 总结 


1. 效果图

如下图所示,当路由变化或发起请求时,出现 Loading 等待效果,此时页面不可见。当路由跳转结束或请求结束时,Loading效果隐藏,页面可见。

 2. 思路分析

接下来从思路和难点入手分析,最终代码实现,解决问题。

 2.1 实现思路

(1) 需要有一个 Loading.vue 组件,可以自己写,也可以用组件库中的组件。

(2) 创建 vuex,通过 vuex store 来管理一个 loading 状态。

(3) 需要在 store 中定义一个计数器,用来追踪正在请求的数量。

(4) 使用 Axios 拦截器,在每次请求开始的时候增加计数器,在请求完成的时候减少计数器。

(5) 根据计数器的值来控制 loading 状态,进而控制 Loading.vue 组件的显示隐藏。

2.2 可能存在的问题

2.2.1 并发请求管理

描述:当应用程序中有多个并发请求时,简单的开始和结束 loading 状态的方式可能会导致 loading 状态提前结束或不正确地显示。例如,如果在 endloading  被调用时还有其他请求未完成,loading 状态应该保持为 true。

参考方法:使用计数器追踪请求数量,如上述所说,Vuex store 中引入一个计数器来追踪正在进行中的请求数量。每次发起请求时增加计数器,请求完成后减少计数器。只有当所有请求都完成后(即计数器归零),才将 loading 置为 false。

2.2.2 请求快速响应和缓存带来的问题

描述:由于网络速度较快或浏览器缓存的原因,某些请求可能会非常快地完成,导致 loading 状态几乎不显示。此外,浏览器可能会从缓存中获取资源,从而绕过了正常的请求流程,使得 loading 状态没有机会被触发。

参考方法:在 endLoading 中引入一个最小延迟(我设置的 300 毫秒)。这样即使请求很快完成,loading 指示器也会显示足够长的时间让用户注意到。可以使用 setTimeOut 来实现这一功能。

3. 代码实现

(1) 如果没有就先下载 Axios 和 vuex。(我是在创建项目的时候就已经下载好了)

下载命令

npm install vuex --savenpm install axios --save

(2) 创建 store 文件,并在其中创建 index.js 文件来定义 Vuex store。然后在主文件 main.js 中引入并使用它。

创建文件夹

/store/index.js 

// 引入 Vue 和 Vuex 库
import Vue from 'vue';
import Vuex from 'vuex';// 使用 Vuex 插件
Vue.use(Vuex);// 创建 Vuex Store 实例
const store = new Vuex.Store({// 定义 state,包含应用程序的状态数据state: {isLoading: false, // 当前是否处于加载状态pendingRequests: 0, // 用来追踪并发请求的数量},// 定义 mutations,用于同步地修改 statemutations: {// 增加正在处理的请求数量incrementPendingRequests(state) {state.pendingRequests++;// 如果这是第一个请求,则设置加载状态为 trueif (state.pendingRequests === 1) {state.isLoading = true;}},// 减少正在处理的请求数量decrementPendingRequests(state) {if (state.pendingRequests > 0) {state.pendingRequests--;// 如果所有请求都已完成,则设置加载状态为 falseif (state.pendingRequests === 0) {state.isLoading = false;}}}},// 定义 actions,用于异步操作和触发 mutationsactions: {// 开始加载状态,通过调用 mutation 增加请求数量startLoading({ commit }) {commit('incrementPendingRequests');},// 结束加载状态,通过调用 mutation 减少请求数量endLoading({ commit }) {commit('decrementPendingRequests');},// 延迟结束加载状态,在指定时间后调用 endLoading actiondelayedEndLoading({ dispatch }, delay = 0) {setTimeout(() => {dispatch('endLoading');}, delay); // 默认延迟时间为 0 毫秒}},// 定义 getters,用于从 state 中派生出一些状态getters: {// 获取当前的加载状态isLoading: state => state.isLoading}
});// 导出 store 实例,以便在应用程序中使用
export default store;

详细注释已在代码中呈现 ↑ ↑ ↑ 

main.js 文件引入 

(3) 创建 axios 文件夹以及相关文件(/api/apiClient.js),添加相应拦截器和请求拦截器,在这里面下文章。

创建文件夹

apiClient.js 文件

// 引入 Axios 库和 Vuex store 实例
import axios from 'axios';
import store from '../store'; // 创建自定义 Axios 实例,用于发起 HTTP 请求
const apiClient = axios.create({baseURL: process.env.VUE_APP_API_URL, // 使用环境变量设置基础 URL,方便跨环境配置timeout: 1000, // 设置请求超时时间为 1 秒headers: { 'Content-Type': 'application/json' } // 设置默认请求头为 JSON 格式
});// 添加请求拦截器,拦截所有发出的请求
apiClient.interceptors.request.use(config => {// 每次请求开始时,调用 Vuex store 的 startLoading action 开始加载状态store.dispatch('startLoading');// 返回配置对象,允许请求继续进行return config;},error => {// 如果请求在发送前发生错误(例如网络错误),调用 endLoading 结束加载状态store.dispatch('endLoading');// 返回一个被拒绝的 Promise,以便处理错误return Promise.reject(error);}
);// 添加响应拦截器,拦截所有接收到的响应
apiClient.interceptors.response.use(response => {// 成功接收到响应后,调用 delayedEndLoading action,在延迟 0.5 秒后结束加载状态store.dispatch('delayedEndLoading', 500); // 成功响应后延迟 0.5 秒结束 loading// 返回响应对象,允许后续处理return response;},error => {// 如果响应失败(例如服务器返回错误码),立即调用 endLoading 结束加载状态store.dispatch('endLoading');// 返回一个被拒绝的 Promise,以便处理错误return Promise.reject(error);}
);// 导出自定义 Axios 实例,以便在整个应用程序中使用
export default apiClient;

详细解说见代码注释 ↑ ↑ ↑ 

(4) 自定义一个 Loading 组件,代码如下。 

Loading.vue 文件

<template><!-- 使用 v-if 指令根据 isLoading 状态显示或隐藏加载指示器 --><div v-if="isLoading" class='base'><!-- 加载动画图片,当 isLoading 为 true 时显示 --><img src="../assets/images/preloader.gif" alt="Loading..."></div>
</template><script>
export default {name: 'Loading',data() {return {}},mounted() {},computed: {isLoading() {// 通过 this.$store.getters 访问 Vuex store 的 getters,// 并返回 isLoading 状态,以控制加载指示器的显示与否return this.$store.getters.isLoading;}}
}
</script><style scoped>
body {background-color: white; font-size: 12px;        
}/* 加载指示器容器样式 */
.base {position: absolute;     top: 50%;               left: 50%;              transform: translate(-50%, -50%);z-index: 9999;          
}
</style>

(5) 实现路由跳转时 loading 效果的呈现。

只需在 /router/index.js 中添加如下代码

// 全局前置守卫
router.beforeEach((to, from, next) => {// 开始加载状态store.dispatch('startLoading');// 继续导航next();
});// 后置钩子
router.afterEach(() => {// 这里可以设置一个短暂的延迟来模拟loading效果,或者直接结束loadingsetTimeout(() => {store.dispatch('endLoading');}, 300); // 可选的延迟时间
});

(6) 在 App.vue 入口文件,放置 Loading.vue组件,当 store 中的 loading 为 true 时,就用Loading.vue组件遮住页面,达到加载中的效果。

App.vue文件

<template><div id="app" :class="{ 'is-loading': $store.getters.isLoading }"><router-view /><Loading /> </div>
</template><script>
import Loading from './components/Loading.vue'
export default {name: 'App',components: {Loading,}
}
</script><style>
*{margin: 0;padding: 0;}
li{list-style:none}
a{text-decoration:none}
#app{height: 100vh;
}
#app.is-loading::before {content: '';position: fixed;top: 0;left: 0;right: 0;bottom: 0;background-color: white;z-index: 9998; /* 确保它在所有元素之上但低于loading组件 */pointer-events: none; /* 不阻止点击事件传递到下面的loading组件 */
}</style>

注意: 

Loading.vue组件需要将页面遮住,需要提一下的就是层级的问题注意一下。

 (7) 然后在页面请求接口或则路由跳转时,就会出现 loading 效果

4. 总结 

最主要的就是vuex的store中的部分逻辑,以及相应拦截器和请求拦截器调用store中的,总结一下实现步骤吧。(1) 引入必要的库  (2) 创建 Vuex Store  (3) 配置 Axios 实例  (4) 创建加载组件  (5) 将组件集成到应用

如果以上内容对你有用的话不妨点赞、关注+收藏,防止下次迷路😀。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/1399.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无源器件-电容

电容器件的参数 基本概念由中学大学物理或电路分析内容获得&#xff0c;此处不做过多分析。 电容的产量占全球电子元器件产品的40%以上。 单位&#xff1a;法拉 F&#xff1b;1F10^6uF&#xff1b;电路中常见的104电容就是10*10^4pF100nF0.1uF C为电容&#xff0c;Rp为绝缘电…

python实现自动登录12306抢票 -- selenium

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 python实现自动登录12306抢票 -- selenium 前言其实网上也出现了很多12306的代码&#xff0c;但是都不是最新的&#xff0c;我也是从网上找别人的帖子&#xff0c;看B站视频&…

Genymotion配套VirtualBox所在地址

在 Genymotion打开虚拟机前需要先打开VirtualBox中的虚拟机 C:\Program Files\Oracle\VirtualBox\VirtualBox.exe 再开启genymotion中的虚拟机开关

浅谈云计算06 | 云管理系统架构

云管理系统架构 一、云管理系统架构&#xff08;一&#xff09;远程管理系统&#xff08;二&#xff09;资源管理系统&#xff08;三&#xff09;SLA 管理系统&#xff08;四&#xff09;计费管理系统 二、安全与可靠性保障&#xff08;一&#xff09;数据安全防线&#xff08;…

泛目录和泛站有什么差别

啥是 SEO 泛目录&#xff1f; 咱先来说说 SEO 泛目录是啥。想象一下&#xff0c;你有一个巨大的图书馆&#xff0c;里面的书架上摆满了各种各样的书&#xff0c;每一本书都代表着一个网页。而 SEO 泛目录呢&#xff0c;就像是一个超级图书管理员&#xff0c;它的任务就是把这些…

WebScoket-服务器客户端双向通信

文章目录 1. 消息推送常用方式介绍2. WebSocket2.1 介绍2.2 客户端API2.3 服务端API 3. 总结 1. 消息推送常用方式介绍 轮询 浏览器以指定的时间间隔向服务器发出HTTP请求&#xff0c;服务器实时返回数据给浏览器。 长轮询 浏览器发出ajax请求&#xff0c;服务器端接收到请求…

uniapp 之 uni-forms校验提示【提交的字段[‘xxx‘]在数据库中并不存在】解决方案

目录 场景问题代码结果问题剖析解决方案 场景 uni-forms官方组件地址 使用uniapp官方提供的组件&#xff0c;某个表单需求&#xff0c;单位性质字段如果是高校&#xff0c;那么工作单位则是高校的下拉选择格式&#xff0c;单位性质如果是其他的类型&#xff0c;工作单位则是手动…

SOME/IP 协议详解——服务发现

文章目录 1. Introduction &#xff08;引言&#xff09;2. SOME/IP Service Discovery (SOME/IP-SD)2.1 General&#xff08;概述)2.2 SOME/IP-SD Message Format2.2.1 通用要求2.2.2 SOME/IP-SD Header2.2.3 Entry Format2.2.4 Options Format2.2.4.1 配置选项&#xff08;Co…

探秘 JMeter (Interleave Controller)交错控制器:解锁性能测试的隐藏密码

嘿&#xff0c;小伙伴们&#xff01;今天咱们要把 JMeter 里超厉害的 Interleave Controller&#xff08;交错控制器&#xff09;研究个透&#xff0c;让你从新手直接进阶成高手&#xff0c;轻松拿捏各种性能测试难题&#xff01; 一、Interleave Controller 深度剖析 所属家族…

C++内存泄露排查

内存泄漏是指程序动态分配的内存未能及时释放&#xff0c;导致系统内存逐渐耗尽&#xff0c;最终可能造成程序崩溃或性能下降。在C中&#xff0c;内存泄漏通常发生在使用new或malloc等分配内存的操作时&#xff0c;但没有正确地使用delete或free来释放这块内存。 在日常开发过程…

rk3568 , buildroot , qt ,使用sqlite, 动态库, 静态库

问题说明&#xff1a; 客户反馈 &#xff0c;buildroot 系统 &#xff0c;使用qt 使用sqlite &#xff0c;有报错&#xff0c;无法使用sqlite. 测试情况说明&#xff1a; 我自己测试&#xff0c;发现&#xff0c; buildroot 自己默认就是 使能了 sqlite 的。 是否解决说明&…

5、波分复用 WDM

这是一张波分复用&#xff08;WDM&#xff09;系统原理示意图&#xff0c;以下是对各部分的详细解析&#xff1a; 业务站&#xff08;OTM&#xff09;部分 光波长转换单元&#xff08;OTU&#xff09;&#xff1a; 图中标注为①&#xff0c;多个 OTU 是波分复用系统的信号源。它…

Spring bean的生命周期和扩展

接AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客&#xff0c;以具体实例看bean生命周期的一些执行阶段 bean生命周期流程 生命周期扩展处理说明实例化:createBeanInstance 构造方法&#xff0c; 如Autowired的构造方法注入依赖bean 如UserSer…

【Rust】引用与借用

目录 思维导图 1. 引用与借用的基本概念 1.1. 引用示例 2. 借用的规则 2.1. 可变借用示例 2.2. 借用的限制 3. 引用的生命周期 思维导图 1. 引用与借用的基本概念 引用的定义&#xff1a;引用是一种指向数据的指针&#xff0c;但与裸指针不同&#xff0c;Rust的引用在编…

Java内存与缓存

Java内存管理和缓存机制是构建高性能应用程序的关键要素。它们之间既有联系又有区别&#xff0c;理解这两者对于优化Java应用至关重要。 Java 内存模型 Java内存模型&#xff08;JMM&#xff09;定义了线程如何以及何时可以看到其他线程修改过的共享变量的值&#xff0c;并且规…

java项目之智慧农贸信息化管理平台(ssm+mybatis+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的码农一枚。今天要和大家聊的是一款基于ssm的智慧农贸信息化管理平台。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 智慧农贸信息化管理平台…

java人脸识别

文章目录 前言 为什么选择虹软呢&#xff1f; 注册虹软账号&#xff0c;下载SDK 将jar包安装到maven本地仓库 项目实战 导入jar包 编写配置文件 Service 编写测试类 人脸识别更多应用 前言 ‌虹软人脸识别技术‌是由虹软公司开发的一系列人脸识别技术&#xff0c;包括…

【学习路线】Python自动化运维 详细知识点学习路径(附学习资源)

学习本路线内容之前&#xff0c;请先学习Python的基础知识 其他路线&#xff1a; Python基础 >> Python进阶 >> Python爬虫 >> Python数据分析&#xff08;数据科学&#xff09; >> Python 算法&#xff08;人工智能&#xff09; >> Pyth…

Nginx代理同域名前后端分离项目的完整步骤

前后端分离项目&#xff0c;前后端共用一个域名。通过域名后的 url 前缀来区别前后端项目。 以 vue php 项目为例。直接上 server 模块的 nginx 配置。 server{ listen 80; #listen [::]:80 default_server ipv6onlyon; server_name demo.com;#二配置项目域名 index index.ht…

73.矩阵置零 python

矩阵置零 题目题目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a; 题解思路分析Python 实现代码代码解释提交结果 题目 题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例…