Vue3如何阻止返回按钮触发重复API调用 改用Vuex存储数据
Vue3 返回页面重复触发Vuex接口请求解决方案
问题核心原因:你当前将接口请求逻辑写在首页组件的mounted生命周期中,Vue Router默认不会缓存已跳转离开的路由组件:从首页跳转到详情页时首页组件会被卸载,点击浏览器返回按钮回到首页时组件会重新执行挂载流程,mounted钩子会无条件触发接口调用,完全没有判断Vuex中是否已有缓存数据。
以下是三种可落地的实现方案,按需选择即可:
方案1:Vuex Action 层统一加缓存判断(优先推荐)
把缓存校验逻辑收敛到Vuex Action中,所有调用该Action的组件都会自动复用缓存,不需要重复写判断逻辑,后续维护成本最低。
改造后的Action代码如下:
actions: { async getCharacters({ state, commit }, page = state.currentPage) { // 缓存校验:当前页码对应列表已存在时,直接返回不发起请求 if (state.list?.length && page === state.currentPage) { return } try { const res = await fetch(`${BASE_URL}character/?page=${page}`); if (res.ok) { const { info, results } = await res.json(); // 注意:mutation中需要同步存储currentPage,保证页码判断逻辑生效 commit('setCharacters', { list: results, currentPage: page }); } } catch (e) { console.log(e); } }, }
如果后续需要支持手动刷新(比如用户点击刷新按钮重载数据),可以给Action增加force参数跳过缓存校验即可:
async getCharacters({ state, commit }, { page = state.currentPage, force = false } = {}) { // force为true时跳过缓存直接发请求 if (!force && state.list?.length && page === state.currentPage) { return } // 原有请求逻辑保持不变 } // 组件中需要强制刷新时调用 this.getCharacters({ force: true })
方案2:组件调用Action前做缓存判断
如果该接口仅在首页单个组件中调用,也可以直接在组件的mounted钩子中先判断Vuex中是否已有数据,有数据就不触发Action。
组件代码改造如下:
import { mapState, mapActions } from 'vuex' export default { computed: { // 先把store中的列表数据映射到组件 ...mapState('characters', ['list']) }, methods: { ...mapActions('characters', ['getCharacters']), }, mounted() { // 仅当列表无缓存数据时发起请求 if (!this.list?.length) { this.getCharacters(); } }, }
该方案缺点是逻辑分散,如果后续其他组件也要调用该接口,需要重复写相同的缓存判断逻辑。
方案3:使用keep-alive缓存路由组件
如果你不仅需要避免重复请求,还希望返回首页时保留用户之前的滚动位置、筛选条件等交互状态,可以使用Vue内置的keep-alive组件包裹路由出口,缓存首页组件实例。
改造App.vue中的路由出口代码:
<template> <!-- include属性填写首页组件的name值,多个组件用逗号分隔 --> <keep-alive include="Home"> <router-view /> </keep-alive> </template>
注意:需要给首页组件设置和include值一致的name属性,否则缓存不生效:
// 首页组件 export default { name: 'Home', // 和include值对应 // 其余组件逻辑 }
开启缓存后,首页组件在跳转离开时不会被销毁,返回时不会重新执行mounted钩子,从根源上避免了重复触发请求。如果需要在组件激活时更新数据,可以在activated生命周期中编写增量更新逻辑。
内容的提问来源于stack exchange,提问作者qweezz
相关产品推荐
相关产品推荐

