Nuxt3中spaLoadingTemplate提前消失:如何保持至请求完成?
问题
在Nuxt3(SSR=false的SPA模式)中遇到如下问题:
- 使用页面中间件时,
spaLoadingTemplate会一直显示直到请求完成:
definePageMeta({ middleware : async () => { await $fetch("/posts"); // 加载完成前loading一直显示 } });
- 但使用
useAsyncData时,spaLoadingTemplate会在请求完成前消失,导致页面空白直至请求结束:
const {data:posts} = await useAsyncData("posts",() => $fetch("/posts")); // 页面打开后loading消失,空白直到请求完成
当前nuxt.config.ts配置:
export default defineNuxtConfig({ ssr: false, devtools: { enabled: false }, nitro: { static: true, }, spaLoadingTemplate: true, });
需求:使用useAsyncData或类似方法时,实现与中间件相同的效果,让spaLoadingTemplate保持显示直到请求完成。
解决方案
方法1:把useAsyncData逻辑封装到页面中间件
既然中间件能让spaLoadingTemplate保持到异步操作完成,可将useAsyncData的逻辑移到中间件中,再把数据存到全局状态或路由元信息供页面调用:
- 创建页面中间件(比如
middleware/fetchPosts.ts):
export default defineNuxtRouteMiddleware(async () => { const { data: posts } = await useAsyncData("posts", () => $fetch("/posts")); // 将数据存入pinia状态管理 usePostsStore().setPosts(posts.value); // 或者直接挂载到路由元信息 // route.meta.posts = posts.value; });
- 在页面中引用该中间件:
definePageMeta({ middleware: ["fetchPosts"] }); // 页面组件中从store或路由元信息取数据 const postsStore = usePostsStore(); const posts = computed(() => postsStore.posts);
方法2:手动控制spaLoadingTemplate的显示状态
Nuxt提供了useNuxtApp()的相关方法,可手动控制loading的显示与隐藏:
const nuxtApp = useNuxtApp(); // 页面开始加载时显示loading nuxtApp.hook("page:start", () => { nuxtApp.provide("spaLoading", true); }); // 在useAsyncData请求完成后隐藏loading const { data: posts } = await useAsyncData("posts", async () => { try { return await $fetch("/posts"); } finally { nuxtApp.provide("spaLoading", false); } });
默认的spaLoadingTemplate已经支持响应spaLoading状态,若使用自定义模板,需确保模板逻辑能正确识别该状态。
方法3:页面内使用pending状态实现局部loading
如果不需要全局loading,可利用useAsyncData返回的pending状态,在页面内实现局部loading:
const { data: posts, pending } = useAsyncData("posts", () => $fetch("/posts"));
模板中对应逻辑:
<template> <div v-if="pending" class="loading">加载中...</div> <div v-else> <!-- 渲染posts内容 --> </div> </template>
注:此方法是页面内局部loading,和全局spaLoadingTemplate的全屏效果不同。
内容的提问来源于stack exchange,提问作者none
相关产品推荐
相关产品推荐

