Vue3中setup使用异步导致页面空白的问题

Vue3中setup使用async异步导致页面空白

平时在使用setup时,避免不了要在里面的函数使用异步,而在setup中直接使用async/await虽然可以得到数据,但是页面会白屏,解决方案如下

只需使用Suspense组件包裹RouterView就可以了

注意,我的RouterView是在根目录App.vue中

<template>
  <Suspense>
    <!-- 使用Suspense 可在setup中使用async -->
    <RouterView />
  </Suspense>
</template>
Vue 3 中,如果要在页面加载前加载数据(即在组件渲染之前获取数据),通常有以下几种方式,具体取决于你使用的是 **选项式 API(Options API)** 还是 **组合式 API(Composition API)**,以及是否使用了 **Vue Router + 路由守卫** 或 **Suspense**。 下面我将给出一个 **使用组合式 API 的推荐方案**,结合 `onMounted` 和 Vue Router 的导航守卫或 `async setup` 配合 `<Suspense>` 实现“在页面显示前加载数据”。 --- ### ✅ 推荐方案:使用 `<Suspense>` + `async setup` 实现页面加载前获取数据 #### 场景说明: 你希望在某个页面组件显示之前,先完成数据的异步加载(比如从 API 获取用户信息),避免页面空白或显示 loading。 --- ### ✅ 示例代码(Vue 3 + Composition API + Suspense) ```vue <!-- App.vue --> <template> <div> <h1>我的应用</h1> <router-view /> </div> </template> ``` ```vue <!-- views/UserProfile.vue --> <template> <div> <h2>用户资料</h2> <p>姓名:{{ user.name }}</p> <p>邮箱:{{ user.email }}</p> </div> </template> <script setup> import { ref } from &#39;vue&#39; import axios from &#39;axios&#39; // 模拟异步加载用户数据 const user = ref(null) // 在 setup使用 async/await,需要配合 Suspense const fetchUser = async () => { const response = await axios.get(&#39;https://jsonplaceholder.typicode.com/users/1&#39;) user.value = response.data } // 执行请求 await fetchUser() </script> ``` ```vue <!-- App.vue 或根组件中使用 Suspense 包裹路由视图 --> <template> <div id="app"> <Suspense> <template #default> <router-view /> </template> <template #fallback> <div>正在加载数据,请稍候...</div> </template> </Suspense> </div> </template> ``` ```js // router/index.js import { createRouter, createWebHistory } from &#39;vue-router&#39; import UserProfile from &#39;../views/UserProfile.vue&#39; const routes = [ { path: &#39;/profile&#39;, component: UserProfile } ] export const router = createRouter({ history: createWebHistory(), routes }) ``` ```js // main.js import { createApp } from &#39;vue&#39; import { router } from &#39;./router&#39; import App from &#39;./App.vue&#39; createApp(App) .use(router) .mount(&#39;#app&#39;) ``` --- ### 🔍 解释: - `setup` 中使用 `await` 是 Vue 3.2+ 支持的 **顶级 `await`** 特性,它会让组件变成异步组件。 - `<Suspense>` 是 Vue 3 提供的内置组件,用于处理异步依赖。它会等待内部组件完成异步操作后再渲染。 - `#fallback` 插槽定义了加载时的占位内容。 - 这种方式真正实现了“**在页面显示前加载数据**”,否则显示 loading。 --- ### ❗️替代方案(不使用 Suspense): 如果你不想用 `<Suspense>`,可以在 `onMounted` 中加载数据,但此时组件已经“挂载”,不算“加载前”。 ```vue <script setup> import { onMounted, ref } from &#39;vue&#39; import axios from &#39;axios&#39; const user = ref(null) const loading = ref(true) onMounted(async () => { const response = await axios.get(&#39;https://jsonplaceholder.typicode.com/users/1&#39;) user.value = response.data loading.value = false }) </script> <template> <div v-if="loading">加载中...</div> <div v-else> <h2>{{ user.name }}</h2> </div> </template> ``` 这种方式是“加载时”而非“加载前”,用户体验略差。 --- ### ✅ 最佳实践建议: | 方案 | 是否真正“加载前” | 推荐度 | |------|------------------|--------| | `async setup` + `<Suspense>` | ✅ 是 | ⭐⭐⭐⭐⭐ | | `onMounted` 异步加载 | ❌ 否(已挂载) | ⭐⭐⭐ | --- ### ✅ 注意事项: 1. 确保你的构建工具(如 Vite / Webpack)支持顶层 `await`。 2. 使用 `Suspense` 时,必须提供 `#default` 和 `#fallback` 插槽。 3. 错误处理:可以结合 `try-catch` 或使用 `ErrorBoundary` 第三方库。 --- ### ✅ 增强版:带错误处理的 async setup ```vue <script setup> import { ref } from &#39;vue&#39; import axios from &#39;axios&#39; const user = ref(null) const error = ref(null) try { const response = await axios.get(&#39;https://jsonplaceholder.typicode.com/users/1&#39;) user.value = response.data } catch (e) { error.value = e.message } // 如果出错,也可以抛出,由外部处理 if (error.value) throw new Error(error.value) </script> <template> <div> <h2>{{ user.name }}</h2> </div> </template> ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值