vue全局配置配置请求拦截加loading (解决多个接口 一次loading)

本文介绍了一种在Vue项目中实现统一加载效果的方法,通过在main.js中定义请求计数变量,并利用Vue-resource或Axios的请求拦截器来动态控制loading显示与关闭,确保了用户体验的同时提升了代码的可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一开始在main.js中定义一个变量设置为当前页面发送接口的数量

var needLoadingRequestCount = 0 //当前正在请求的数量

 

接下来在请求拦截中写(我是写在vue-resource中 axios同理)

Vue.http.interceptors.push((request, next) => {  

    //这里是请求发起之前做的预处理

    needLoadingRequestCount++  //每次发送一个请求就进行++

    Indicator.open('加载中...');   //这里是mint-ui的loading

  next((response) => { //这里是接口响应之后传给then之前对response的逻辑处理和修改

        needLoadingRequestCount--  //调用完一个接口就进行-1

        if(needLoadingRequestCount == 0){  //当接口都调用完时

            setTimeout(function(){

                Indicator.close();  //关闭loading
          
              },100)
     
           }
   
     })

});

 

<think>我们正在讨论如何在 ofetch 请求拦截中显示 loading 状态。这通常涉及在请求开始显示一个加载指示器(如旋转图标或进度条),在请求结束隐藏它。 由于 ofetch 提供了请求拦截(onRequest)和响应拦截(onResponse、onResponseError)钩子,我们可以利用这些钩子来控制 loading 状态。 思路: 1. 在请求开始(onRequest)显示 loading 2. 在请求结束(无论成功或失败,即 onResponse 和 onResponseError)隐藏 loading 但是,需要注意的是,如果多个请求发生,我们可能不希望每个请求都触发一次 loading 的显示和隐藏,而是希望有一个全局加载状态(例如,当有至少一个请求在进行显示 loading)。因此,我们可以使用一个计数器来跟踪当前正在进行的请求数量。 以下是一个示例实现: 步骤: a) 创建一个可重用的 ofetch 实例,并配置拦截器。 b) 使用一个计数器(如 pendingRequestCount)来跟踪当前挂起的请求数量。 c) 当 pendingRequestCount 从0变为1,显示 loading;当 pendingRequestCount 从1变为0,隐藏 loading。 示例代码(在Vue中,但原理适用于任何框架): ```typescript import { ofetch } from 'ofetch' // 用于跟踪当前挂起的请求数量 let pendingRequestCount = 0 // 创建 ofetch 实例 const api = ofetch.create({ // 基础配置 baseURL: 'https://api.example.com', // 请求拦截器 onRequest({ request, options }) { // 每次请求开始,计数器1 pendingRequestCount++ // 如果这是第一个请求,则显示loading if (pendingRequestCount === 1) { // 这里以Vue为例,实际项目中可以使用任何方式显示loading,例如修改一个全局状态 // 假设我们有一个全局状态管理(如Vuex/Pinia)或一个可观察对象来管理loading状态 showLoading() // 自定义显示loading的函数 } }, // 响应拦截器(成功响应) onResponse({ response, options }) { // 请求结束,计数器减1 pendingRequestCount-- // 如果计数器归零,则隐藏loading if (pendingRequestCount === 0) { hideLoading() // 自定义隐藏loading的函数 } }, // 响应错误拦截器 onResponseError({ error, response, options }) { // 请求结束,计数器减1(错误情况也要减) pendingRequestCount-- if (pendingRequestCount === 0) { hideLoading() } // 可以在这里统一处理错误,例如根据错误状态码弹出提示 throw error // 或者返回一个自定义错误 } }) // 使用示例 api('/user/profile').then(...) // 显示和隐藏loading的函数,具体实现取决于你的UI框架和loading组件 function showLoading() { // 例如,在Vue中可以通过修改一个全局loading状态为true来显示loading // 或者直接操作DOM显示一个loading元素 console.log('显示loading') } function hideLoading() { console.log('隐藏loading') } ``` 注意: 1. 计数器(pendingRequestCount)是全局的,因此多个请求会共享同一个计数器。 2. 当多个请求发生loading 会在第一个请求开始显示,并在最后一个请求结束隐藏。 3. 如果请求非常快,可能会出现 loading 闪烁的情况。可以通过设置一个最小显示间(例如200ms)来避免,但这需要额外的逻辑。 关于最小显示间:我们可以使用一个定器,在显示loading设置一个最小显示间(比如200ms),然后在这个间之后才允许隐藏。但要注意,如果同多个请求,我们可能需要更复杂的控制。 另一种方案是使用一个独立的loading状态管理,例如: - 显示loading记录间戳,并设置一个最小持续间(例如200ms) - 在隐藏loading,检查从显示开始是否已经过了最小持续间,如果没到则等待剩余间 不过,这可能会使代码变得复杂,根据项目需求选择是否实现。 在Vue/Nuxt项目中,我们可以结合使用全局状态(如Pinia)来管理loading状态,这样可以在多个组件中共享。 例如,在Nuxt3中,我们可以创建一个可组合函数(composable)来管理loading状态,并在拦截器中更新这个状态。 总结:通过ofetch的拦截器和全局计数器,我们可以实现一个全局loading效果,适用于多个并发请求的场景。 引用说明:本文中未直接引用用户提供的引用内容,因为用户提供的引用内容主要涉及Spring配置解析、容器网络配置和MyBatis分页查询,与当前问题无关。因此,我们基于ofetch文档和常见实践提供解决方案[^1][^2][^3]。</think>### 在 ofetch 请求拦截器中实现 Loading 状态 通过 ofetch 的拦截器系统,可以轻松实现请求过程中的 Loading 状态管理。以下是完整实现方案: ```typescript import { ofetch } from 'ofetch' // 创建全局状态(Vue/Pinia/React 等状态管理) const loadingState = ref(false) let activeRequests = 0 // 跟踪活动请求数量 // 创建 ofetch 实例 const api = ofetch.create({ baseURL: 'https://api.example.com', onRequest: ({ options }) => { // 请求开始显示 Loading activeRequests++ loadingState.value = true // 添请求间戳(用于防止快速请求闪烁) options._requestTime = Date.now() }, onResponse: ({ response, options }) => { // 请求结束隐藏 Loading handleLoadingComplete(options) }, onResponseError: ({ error, options }) => { // 错误也隐藏 Loading handleLoadingComplete(options) throw error } }) // 处理 Loading 状态更新 function handleLoadingComplete(options: any) { activeRequests-- // 确保所有请求都完成后再隐藏 if (activeRequests <= 0) { activeRequests = 0 // 最小显示间(避免闪烁) const minShowTime = 300 const elapsed = Date.now() - options._requestTime const delay = Math.max(0, minShowTime - elapsed) setTimeout(() => { loadingState.value = false }, delay) } } // 在组件中使用 function fetchData() { api('/data') .then(data => console.log(data)) .catch(error => console.error(error)) } ``` #### 关键实现点: 1. **全局状态管理** - 使用 `loadingState` 控制 UI 显示状态 - `activeRequests` 计数器确保多个并发请求状态正确[^1] 2. **防闪烁处理** ```typescript // 确保 Loading 至少显示 300ms const minShowTime = 300 const elapsed = Date.now() - options._requestTime const delay = Math.max(0, minShowTime - elapsed) ``` 避免快速请求导致的 UI 闪烁[^2] 3. **多请求处理** ```typescript activeRequests++ // 请求开始 activeRequests-- // 请求结束 if (activeRequests <= 0) loadingState.value = false ``` 确保所有并发请求完成后才隐藏 Loading 4. **框架集成示例(Vue3)** ```vue <template> <div> <button @click="fetchData">加载数据</button> <div v-if="loading">加载中...</div> </div> </template> <script setup> import { useLoadingStore } from './store' const loading = useLoadingStore() const fetchData = async () => { try { const data = await api('/data') } catch (e) { console.error(e) } } </script> ``` #### 高级配置选项 | 参数 | 类型 | 说明 | 默认值 | |------|------|------|--------| | `minLoadingTime` | number | Loading 最小显示间 | 300ms | | `excludePaths` | string[] | 跳过 Loading 的 API 路径 | [] | | `customLoader` | function | 自定义 Loading 处理器 | - | ```typescript // 扩展配置示例 const api = ofetch.create({ // ...其他配置 onRequest: ({ request, options }) => { // 排除特定路径 if (options.excludePaths?.includes(request)) return activeRequests++ loadingState.value = true // 使用自定义加载器 if (options.customLoader) { options.customLoader.start() } } }) // 使用自定义配置 api('/no-loading', { excludePaths: ['/no-loading'] }) ``` > **最佳实践**:建议将 Loading 逻辑封装为可重用插件,在 Nuxt3 中可通过 `nuxt-plugin` 全局注册[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值