Nuxt切换i18n语言时asyncData拉取的数据未正常更新
问题原因
首先你看到的Observer对象不是异常数据:
- Nuxt 2基于Vue 2实现,所有挂载到组件上的响应式数据都会被Vue包裹为Observer对象用于依赖收集。首次加载首页时
asyncData在服务端执行,打印的是未经过响应式处理的原始数据;切换语言走客户端路由跳转时,asyncData在客户端执行,返回的数据会被Vue做响应式转换,所以控制台显示Observer标记是正常现象,你展开对象能看到正确的法语内容就证明接口请求本身是成功的。
页面内容消失是你的代码存在几个明确问题:
- 语言映射逻辑有漏洞:三个独立的if判断没有兜底规则,一旦i18n当前locale值和判断条件不完全匹配(比如葡萄牙语配置的code是
pt-PT而非pt),传给接口的lang参数就会是undefined,接口返回不符合预期的数据。 - 异常捕获逻辑缺失:catch块仅打印错误,没有返回符合结构的兜底数据,一旦请求出现异常,组件内的
projects/articles/services变量会变成undefined,模板访问属性时直接抛出JS错误导致页面空白。 - 同路由组件复用问题:切换语言时URL仅变化语言前缀,Nuxt默认会复用页面组件实例,部分场景下会导致数据更新不触发视图重渲染。
- 原生fetch的错误捕获漏洞:fetch仅在网络故障时抛出异常,接口返回4xx/5xx状态码时不会进入catch,容易出现返回数据格式异常的问题。
修复方案
按以下步骤修改代码即可解决问题:
- 替换零散的if判断为映射表,增加默认语言兜底,避免lang参数异常:
// 替换原来的三个if判断 const langMap = { en: 'en', pt: 'pt-PT', 'pt-PT': 'pt-PT', fr: 'fr' } const lang = langMap[i18n.locale] || 'en'
- 封装统一的请求方法,增加HTTP状态码校验,用
Promise.all并行请求提升加载速度,同时修正catch块返回固定结构的兜底数据:
async asyncData({ store, i18n }) { const langMap = { en: 'en', pt: 'pt-PT', 'pt-PT': 'pt-PT', fr: 'fr' } const lang = langMap[i18n.locale] || 'en' // 统一请求方法 const fetchStrapi = async (path) => { const res = await fetch(`${store.state.apiUrl}${path}&locale=${lang}`) if (!res.ok) throw new Error(`接口请求失败,状态码:${res.status}`) return res.json() } try { // 并行请求,比逐个await速度更快 const [services, projects, articles] = await Promise.all([ fetchStrapi('/project-categories?populate=*'), fetchStrapi('/projects?populate=*'), fetchStrapi('/articles?populate=*') ]) return { projects: projects.data, articles: articles.data, services: services.data } } catch (error) { console.log(error) // 兜底返回空数组,保证模板访问属性不会报错 return { projects: [], articles: [], services: [] } } }
- 解决同路由组件复用问题:找到项目布局文件(默认是
layouts/default.vue),将原来的<nuxt />组件增加$route.fullPath作为key,保证路由(含语言参数)变化时组件强制刷新:
<!-- 原来的<nuxt />替换为下面的写法 --> <nuxt :key="$route.fullPath" />
- 检查模板中的属性访问路径是否正确:Strapi v4返回的条目属性都在
attributes字段下,比如渲染项目标题需要写{{ project.attributes.title }},不要漏写attributes层级。
内容的提问来源于stack exchange,提问作者NoX
相关产品推荐
相关产品推荐

