Nuxt 3 SSR博客动态内容加载报错:content未定义
问题分析与解决方案
核心问题
你遇到的错误本质是异步请求未完成就尝试访问数据:
- 调用
postStore.getPostBySlug(slug)时没加await,导致后续直接取postStore.currentPost[0]时,接口还没返回数据,currentPost还是空数组,currentPost[0]就是undefined,自然读不到content。 - 刷新页面能解决是因为刷新时服务端会重新执行数据请求,渲染时数据已经就绪;但页面跳转时是客户端导航,异步请求还在pending就开始渲染,触发错误。
修复步骤
1. 修正页面中的异步逻辑
把页面脚本里的异步调用改成正确的等待方式,确保数据返回后再赋值:
<template> <div class='grid grid-cols-6 gap-2'> <!-- 加加载状态避免空内容或错误 --> <div v-if="!post">加载中...</div> <div v-else>{{ post.content }}</div> </div> </template> <script setup lang="ts"> import { useRoute } from 'vue-router'; import { usePostStore } from '../../../../stores/post'; import { ref } from 'vue'; const postStore = usePostStore() const route = useRoute() const slug = route.params.slug const post = ref(null) // 必须await异步请求完成,再获取数据 await postStore.getPostBySlug(slug) post.value = postStore.currentPost[0] definePageMeta({ layout: "posts", }) // 处理post为null的情况,避免标题报错 useHead({ title: post.value ? post.value.title : '博文详情' }) </script>
2. 优化Pinia Store的错误处理
在getPostBySlug里加错误捕获,避免接口失败导致状态异常:
import { defineStore } from 'pinia'; export const usePostStore = defineStore('post-store', () => { const posts = ref([]); const pressReleases = ref([]); const news = ref([]); const currentPost = ref([]); // ...其他方法不变 async function getPostBySlug(slug) { try { const { data, error } = await useAsyncGql({ operation: 'getPostBySlug', variables: { slug: slug }, }); if (error) throw error currentPost.value = data._rawValue.post; } catch (err) { console.error('获取博文失败:', err) currentPost.value = [] // 出错时重置状态,避免旧数据干扰 } } return { posts, currentPost, pressReleases, news, getPressReleases, getNews, getPostBySlug, getAllPosts, }; });
3. 适配Nuxt SSR的状态同步(推荐)
用Nuxt自带的useAsyncData处理数据获取,自动适配SSR和客户端导航的状态同步:
<template> <div class='grid grid-cols-6 gap-2'> <div v-if="pending">加载中...</div> <div v-else-if="error">加载失败,请重试</div> <div v-else>{{ post?.content }}</div> </div> </template> <script setup lang="ts"> import { useRoute } from 'vue-router'; import { usePostStore } from '../../../../stores/post'; const route = useRoute() const slug = route.params.slug const postStore = usePostStore() // useAsyncData会自动缓存数据,避免重复请求,同时适配SSR const { data: post, pending, error } = useAsyncData('post-' + slug, async () => { await postStore.getPostBySlug(slug) return postStore.currentPost[0] }) definePageMeta({ layout: "posts", }) useHead({ title: post.value ? post.value.title : '博文详情' }) </script>
额外注意点
- 模板里可以用可选链操作符
{{ post?.content }},即使post为undefined也不会报错。 - 始终保留加载状态和错误提示,提升用户体验。
内容的提问来源于stack exchange,提问作者Calvin Coleman
相关产品推荐
相关产品推荐

