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

devtools/2025/1/16 4:25:21/

目录

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.ppmy.cn/devtools/150840.html

相关文章

51单片机入门基础

目录 一、基础知识储备 &#xff08;一&#xff09;了解51单片机的基本概念 &#xff08;二&#xff09;掌握数字电路基础 &#xff08;三&#xff09;学习C语言编程基础 二、开发环境搭建 &#xff08;一&#xff09;硬件准备 &#xff08;二&#xff09;软件准备 三、…

Jenkins简单的安装运行

一、下载 官网下载&#xff1a;https://www.jenkins.io/download/ 清华大学开源软件镜像站&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/jenkins/ 官网资料丰富&#xff0c;介绍了各种平台安装以及下载。安装简单&#xff0c;按照说明来就行。下面我介绍一个非常简单的…

Linux---history查看命令历史记录命令

history命令是Linux系统中用于显示和管理用户之前执行过的命令列表的实用工具。以下是history命令的详细教程&#xff1a; 一、基本功能 history命令能够显示用户在当前shell会话或之前会话中执行过的所有命令。这对于回顾之前的操作、复制某个命令进行修改再次执行等场景非常…

第六章:网页设计

文章目录&#xff1a; 一&#xff1a;网页设计 1.基本概念 1.1 网页 1.2 网站 1.3 工具 2.HTML语言 2.1 基础 2.2 标记 2.2.1 结构 2.2.2 文本 2.2.3 功能 2.2.4 表单 2.3 属性 二&#xff1a;IIS 1.定义 2.主要功能 3.特点与优势 4.应用场景 4.1 安装IIS …

Elasticsearch实战应用:从基础到高级

引言 Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎&#xff0c;能够快速地存储、搜索和分析大量数据。它广泛应用于日志分析、全文搜索、实时数据分析等场景。本文将深入探讨 Elasticsearch 的实战应用&#xff0c;涵盖从基础概念到高级应用的各个方面。 1…

深入详解自然语言处理(NLP)中的语言模型:BERT、GPT及其他预训练模型的原理与应用

【自然语言处理】——深入详解自然语言处理&#xff08;NLP&#xff09;中的语言模型&#xff1a;BERT、GPT及其他预训练模型的原理与应用 自然语言处理&#xff08;NLP&#xff09;是人工智能&#xff08;AI&#xff09;领域中的重要分支&#xff0c;旨在通过计算机处理和分析…

zig语言初探:来写贪吃蛇游戏

Zig 语言简介&#xff1a; Zig 是一种系统编程语言&#xff0c;注重安全、性能和可维护性。具有简洁的语法&#xff0c;支持强大的编译时功能&#xff0c;旨在取代 C 语言&#xff0c;适合系统级编程。 本文使用 Zig 实现贪吃蛇游戏&#xff0c;利用 curses 库进行终端显示&…

RocketMQ

目录 一、什么是RocketMQ 主要特点&#xff1a; 应用场景&#xff1a; 二、RocketMQ的使用 添加依赖 配置RocketMQ 创建生产者服务 创建消费者监听器 编写测试Controller 启动Spring Boot应用 三、RocketMQ与Kafka的异同 相似点 不同点 一、什么是RocketMQ Rocke…