【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.mzph.cn/bicheng/68092.shtml

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

相关文章

Github配置ssh key,密钥配对错误怎么解决?

解决密钥配对的方案如下&#xff1a; 方法一、最有效的方案&#xff1a;重新配置&#xff0c;验证 SSH 密钥是否已添加到 GitHub 确保您的 SSH 密钥已经正确添加到了 GitHub 账户中。您可以打开命令行控制台&#xff08;cmd/powerShell都可以&#xff09;&#xff0c;按照以下…

Java基础知识(六) -- 常用类

1.包装类 1.1 概述 Java提供了两个类型系统&#xff0c;基本类型与引用类型&#xff0c;使用基本类型在于效率&#xff0c;但当使用只针对对象设计的API或新特性(例如泛型)&#xff0c;那么基本数据类型的数据就需要用包装类来包装。 序号基本数据类型包装类&#xff08;java…

【Linux】深入理解文件系统(超详细)

目录 一.磁盘 1-1 磁盘、服务器、机柜、机房 &#x1f4cc;补充&#xff1a; &#x1f4cc;通常网络中用高低电平&#xff0c;磁盘中用磁化方向来表示。以下是具体说明&#xff1a; &#x1f4cc;如果有一块磁盘要进行销毁该怎么办&#xff1f; 1-2 磁盘存储结构 ​编辑…

【硬件介绍】Type-C接口详解

一、Type-C接口概述 Type-C接口特点&#xff1a;以其独特的扁头设计和无需区分正反两面的便捷性而广受欢迎。这种设计大大提高了用户的使用体验&#xff0c;避免了传统USB接口需要多次尝试才能正确插入的问题。Type-C接口内部结构&#xff1a;内部上下两排引脚的设计虽然可能不…

Linux第二课:LinuxC高级 学习记录day02

2.4、shell中的特殊字符 2.4.4、命令置换符 或者 $() 反引号&#xff1a;esc下面的按键&#xff0c;英文状态下直接按 功能&#xff1a;将一个命令的输出作为另一个命令的参数 echo 不会认为hostname是一个命令 加上 之后&#xff0c;先执行hostname&#xff0c;拿到主机名…

图生生AI描述生图:一句话生成蛇年海报素材

2025年春晚吉祥物“巳升升”的亮相&#xff0c;引发了广泛讨论。其整体造型参考甲骨文中的“巳”字&#xff0c;以青绿色为主调&#xff0c;象征春意盎然、蓬勃生机。从头部轮廓、脸颊螺旋形状到五官设计&#xff0c;都蕴含着丰富的传统文化元素。巳升升的亮相&#xff0c;春节…

KMP前缀表 ≈ find() 函数——28.找出字符串中第一个匹配项的下标【力扣】

class Solution { public: //得到前缀表void getNext(int *next,string needle){int j0;for(int i1;i<needle.size();i){while(j>0 && needle[j]!needle[i]) jnext[j-1];//**j>0**>j0是出口if(needle[i]needle[j]) j;next[i]j;//若写入if中&#xff0c;则该…

前端笔记----

在我的理解里边一切做页面的代码都是属于前端代码。 之前用过qt框架&#xff0c;也是用来写界面的&#xff0c;但是那是用来写客户端的&#xff0c;而html是用来写web浏览器的&#xff0c;相较之下htmlcssJavaScript写出来的界面是更加漂亮的。这里就记录我自个学习后的一些笔…

FairGuard游戏安全2024年度报告

导 读&#xff1a;2024年&#xff0c;国内游戏市场实际销售收入3257.83亿元&#xff0c;同比增长7.53%&#xff0c;游戏用户规模6.74亿人&#xff0c;同比增长0.94%&#xff0c;市场收入与用户规模双双实现突破&#xff0c;迎来了历史新高点。但游戏黑灰产规模也在迅速扩大&…

C++ STL之容器介绍(vector、list、set、map)

1 STL基本概念 C有两大思想&#xff0c;面向对象和泛型编程。泛型编程指编写代码时不必指定具体的数据类型&#xff0c;而是使用模板来代替实际类型&#xff0c;这样编写的函数或类可以在之后应用于各种数据类型。而STL就是C泛型编程的一个杰出例子。STL&#xff08;Standard …

uniapp 抖音小程序 getUserProfile:fail must be invoked by user tap gesture

项目场景&#xff1a; uniapp 抖音小程序 getUserProfile:fail must be invoked by user tap gesture,在实现点击头像需要出发抖音小程序获取用户原生头像的操作中&#xff0c;无论如何也无法触发抖音的原生窗口&#xff01; 问题描述 这个问题我找了很多博主的方法&#xff…

.NET Core NPOI 导出图片到Excel指定单元格并自适应宽度

NPOI&#xff1a;支持xlsx&#xff0c;.xls&#xff0c;版本>2.5.3 XLS&#xff1a;HSSFWorkbook&#xff0c;主要前缀HSS&#xff0c; XLSX&#xff1a;XSSFWorkbook&#xff0c;主要前缀XSS&#xff0c;using NPOI.XSSF.UserModel; 1、导出Excel添加图片效果&#xff0…

SpringCloud微服务:基于Nacos组件,整合Dubbo框架

dubbo和fegin的差异 一、Feign与Dubbo概述 Feign是一个声明式的Web服务客户端&#xff0c;使得编写HTTP客户端变得更简单。通过简单的注解&#xff0c;Feign将自动生成HTTP请求&#xff0c;使得服务调用更加便捷。而Dubbo是一个高性能、轻量级的Java RPC框架&#xff0c;提供了…

Jenkins触发器--在其他项目执行后构建

前言&#xff1a; jenkins中有多种触发器可用&#xff0c;可以方便的控制构建的启动 这里简单介绍下项目后构建的配置方法 1. 解释&#xff1a; Build after other projects are built Set up a trigger so that when some other projects finish building, a new build is…

4、蓝牙打印机-定时器驱动

蓝牙打印机实现打印内容&#xff0c;需要先通过定时器发送固定的节拍驱动步进电机转动&#xff0c;从而驱动打印头打印相应的内容。 因此想要实现打印&#xff0c;先要实现定时器功能。 本例采用通用定时器2完成发送节拍功能。 1、硬件 定时器总线 由上图知道TIM2是挂载在A…

(纯小白教程)Mac OS中安装配置Anaconda及常用conda命令回顾

本教程介绍了如何在Mac OS系统中下载、安装、配置 Anaconda3&#xff0c;并介绍了换源的方法&#xff0c;最后介绍了常用的conda命令。本教程适用于苹果系统&#xff0c;如需要在Windows系统或者Liunx系统中安装Anaconda3&#xff0c;可移步至主页的其他博客。 &#xff08;纯…

JVM面试相关

JVM组成 什么是程序计数器 详细介绍Java堆 什么是虚拟机栈 能不能解释一下方法区&#xff1f; 直接内存相关 类加载器 什么是类加载器&#xff0c;类加载器有哪些 什么是双亲委派模型 类加载过程 垃圾回收 对象什么时候可以被垃圾回收器回收 JVM垃圾回收算法有那些 JVM的分代…

Netty 入门学习

前言 学习Spark源码绕不开通信&#xff0c;Spark通信是基于Netty实现的&#xff0c;所以先简单学习总结一下Netty。 Spark 通信历史 最开始: Akka Spark 1.3&#xff1a; 开始引入Netty&#xff0c;为了解决大块数据&#xff08;如Shuffle&#xff09;的传输问题 Spark 1.6&…

[笔记] 使用 Jenkins 实现 CI/CD :从 GitLab 拉取 Java 项目并部署至 Windows Server

随着软件开发节奏的加快&#xff0c;持续集成&#xff08;CI&#xff09;和持续部署&#xff08;CD&#xff09;已经成为确保软件质量和加速产品发布的不可或缺的部分。Jenkins作为一款广泛使用的开源自动化服务器&#xff0c;为开发者提供了一个强大的平台来实施这些实践。然而…

qt QPainter setViewport setWindow viewport window

使用qt版本5.15.2 引入viewport和window目的是用于实现QPainter画出来的内容随着窗体伸缩与不伸缩两种情况&#xff0c;以及让QPainter在widget上指定的区域(viewport)进行绘制/渲染&#xff08;分别对应下方demo1&#xff0c;demo2&#xff0c;demo3&#xff09;。 setViewpo…