You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vue 3、Vuex结合Axios时避免重复API请求?

在Vue 3 + Vuex + Axios中避免重复API请求的实现方案

要实现首次访问路由时加载API数据、后续直接从缓存获取的需求,核心是在Vuex中维护数据缓存、加载状态和已加载标记,结合路由守卫触发请求,同时在action层做缓存判断与并发请求拦截。

1. 设计Vuex模块管理缓存与请求状态

先在Vuex中定义一个专门的模块,处理数据缓存、加载状态控制和请求逻辑:

// store/modules/dataModule.js
import axios from 'axios'

const state = {
  cachedData: null,       // 存储缓存的数据
  isLoading: false,       // 标记是否正在请求数据
  isLoaded: false         // 标记是否完成首次加载
}

const mutations = {
  SET_CACHED_DATA(state, data) {
    state.cachedData = data
  },
  SET_LOADING(state, status) {
    state.isLoading = status
  },
  SET_LOADED(state, status) {
    state.isLoaded = status
  }
}

const actions = {
  async fetchData({ state, commit }) {
    // 1. 已加载过数据,直接返回缓存
    if (state.isLoaded) {
      return state.cachedData
    }
    // 2. 正在请求中,等待请求完成后返回结果(防止并发重复请求)
    if (state.isLoading) {
      return new Promise(resolve => {
        const checkInterval = setInterval(() => {
          if (!state.isLoading) {
            clearInterval(checkInterval)
            resolve(state.cachedData)
          }
        }, 50)
      })
    }
    // 3. 发起新请求
    commit('SET_LOADING', true)
    try {
      const response = await axios.get('/api/your-target-endpoint')
      commit('SET_CACHED_DATA', response.data)
      commit('SET_LOADED', true)
      return response.data
    } catch (error) {
      console.error('数据请求失败:', error)
      throw error // 抛出错误让调用方处理
    } finally {
      commit('SET_LOADING', false)
    }
  },
  // 可选:重置缓存,用于需要强制刷新数据的场景
  resetDataCache({ commit }) {
    commit('SET_CACHED_DATA', null)
    commit('SET_LOADED', false)
  }
}

const getters = {
  getCachedData: state => state.cachedData,
  isDataLoading: state => state.isLoading,
  isDataLoaded: state => state.isLoaded
}

export default {
  namespaced: true,
  state,
  mutations,
  actions,
  getters
}

记得将该模块注册到Vuex Store:

// store/index.js
import { createStore } from 'vuex'
import dataModule from './modules/dataModule'

export default createStore({
  modules: {
    dataModule
  }
})

2. 在路由守卫中触发请求

在目标路由的beforeEnter守卫里调用Vuex的fetchData action,确保首次访问路由时自动请求数据,后续访问直接走缓存:

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import store from '@/store'
import TargetComponent from '@/components/TargetComponent.vue'

const routes = [
  {
    path: '/target-route',
    name: 'TargetRoute',
    component: TargetComponent,
    beforeEnter: async (to, from, next) => {
      // 触发数据请求,自动走缓存逻辑
      await store.dispatch('dataModule/fetchData')
      next()
    }
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

3. 组件中直接使用缓存数据

组件无需再发起请求,直接通过Vuex的getters获取缓存数据和状态:

<!-- components/TargetComponent.vue -->
<template>
  <div class="data-container">
    <div v-if="isLoading" class="loading">加载中...</div>
    <div v-else-if="cachedData" class="content">
      <!-- 渲染数据 -->
      <pre>{{ cachedData }}</pre>
    </div>
    <div v-else class="empty">暂无数据</div>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import { useStore } from 'vuex'

const store = useStore()
const cachedData = computed(() => store.getters['dataModule/getCachedData'])
const isLoading = computed(() => store.getters['dataModule/isDataLoading'])
</script>

额外优化说明

  • 若需要强制刷新数据(如用户提交表单后),可先调用resetDataCache action,再调用fetchData即可重新请求最新数据。
  • 如需按请求参数做细粒度缓存,可将cachedData改为对象,用请求参数作为key存储不同缓存结果。

内容的提问来源于stack exchange,提问作者Uzzal Hossain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 23:05:25