Vue3异步拉取数据在locale切换时无法更新问题
问题原因
核心问题出在两层逻辑错误:
- 原
fetchData工具函数每次调用都会返回一个全新创建的ref实例,函数内部的异步请求只会更新这个内部ref的value,不会同步给外层变量。首次加载能正常渲染,是因为初始化时外层fetchedData的value指向第一个内部ref,请求完成后内部ref更新,视图碰巧能读取到值;但语言切换时,你给fetchedData.value赋值的是新创建的第二个内部ref对象,视图不会自动追踪这个新ref内部的value变化,自然不会更新。 - 原逻辑没有对异步请求做统一的状态管理,既无法判断请求完成时机,也存在locale切换时store内语言值未同步更新,导致拉取到旧语言数据的边缘问题。
修复步骤
1. 改造fetchData工具函数
移除工具函数内部的ref创建逻辑,改成标准异步函数,直接返回请求结果,响应式状态统一交给组件维护,从根源避免嵌套ref问题:
// utils/universal-fetch.js export async function fetchData(section, key) { const requestConfig = { method: "GET", headers: { "Content-Type": "application/json" }, }; const response = await fetch( `http://localhost:4000/api/${section}/?api-key=${key}`, requestConfig ); const data = await response.json(); if (!response.ok) { const errorMsg = data?.message || response.statusText; throw new Error(errorMsg); } return data; }
2. 调整组件内调用逻辑
组件内统一维护响应式状态,封装独立的数据加载方法,在初始化和语言切换时调用,等请求完成后再更新数据:
<script setup> import { fetchData } from "../../utils/universal-fetch"; import { ref, watch, onMounted } from "vue"; import { useStore } from "../../stores/language.js"; import { useI18n } from "vue-i18n"; import AOS from "aos"; const store = useStore(); const { locale } = useI18n({ useScope: "global" }); // 响应式状态直接在组件内初始化,不要嵌套其他ref const fetchedData = ref(null); const loading = ref(false); // 可选:加加载状态优化交互 // 封装统一的数据拉取逻辑 const loadHomeSectionData = async () => { loading.value = true; try { const res = await fetchData("homeFirstSection", store.getLanguage); fetchedData.value = res; } catch (error) { console.error("数据拉取失败:", error); } finally { loading.value = false; } }; onMounted(() => { AOS.init(); loadHomeSectionData(); }); // 监听语言变化重新拉取数据 watch( () => locale.value, () => { loadHomeSectionData(); } ); </script>
可选优化
如果不想在onMounted里单独调用首次加载,可以给watch加immediate: true配置,组件初始化时会自动触发一次加载逻辑,代码更简洁:
watch( () => locale.value, () => { loadHomeSectionData(); }, { immediate: true } );
加了这个配置就可以删掉onMounted里的loadHomeSectionData()调用。
内容的提问来源于stack exchange,提问作者petomuro
相关产品推荐
相关产品推荐

