Vue.js:Firebase数据加载时添加骨架屏加载组件的实现方案
实现Firestore加载时显示骨架屏的方案
核心思路
放弃Suspense,改用状态驱动的条件渲染,通过手动管理加载状态来控制骨架屏和实际内容的切换。
具体实现步骤
1. 定义加载状态变量
根据你使用的Vue API风格,添加加载状态:
- 选项式API:
<script> export default { data() { return { isLoading: true, data: null } } } </script>
- 组合式API:
<script setup> import { ref } from 'vue' const isLoading = ref(true) const data = ref(null) </script>
2. 调整Firestore数据请求逻辑
在请求数据时手动控制加载状态,请求完成(成功/失败)后关闭加载态:
// 组合式API示例,需提前引入Firestore相关方法 import { db } from '@/firebase/config' import { collection, getDocs } from 'firebase/firestore' import { onMounted } from 'vue' async function fetchData() { isLoading.value = true try { const querySnapshot = await getDocs(collection(db, '你的集合名')) data.value = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })) } catch (err) { console.error('数据加载失败:', err) } finally { isLoading.value = false } } // 组件挂载时触发请求 onMounted(() => { fetchData() })
3. 模板中条件渲染内容
根据isLoading的值切换显示骨架屏或实际数据:
<template> <div class="page-container"> <!-- 骨架屏组件 --> <SkeletonScreen v-if="isLoading" /> <!-- 实际数据内容 --> <div v-else class="data-content"> <div v-for="item in data" :key="item.id" class="data-item"> {{ item.content }} </div> </div> </div> </template>
4. 可选:添加超时处理
如果担心请求过慢,可设置超时逻辑避免骨架屏无限显示:
async function fetchData() { isLoading.value = true // 设置3秒超时 const timeout = new Promise((_, reject) => setTimeout(() => reject(new Error('加载超时')), 3000)) try { const querySnapshot = await Promise.race([ getDocs(collection(db, '你的集合名')), timeout ]) data.value = querySnapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })) } catch (err) { console.error('数据加载失败:', err) } finally { isLoading.value = false } }
为什么不用Suspense?
Firebase的API(如getDocs)虽返回Promise,但Suspense要求异步依赖是组件级异步导入或setup函数返回Promise,而Firestore数据请求属于组件内部异步操作,不符合Suspense的触发条件,状态驱动的方式更直接可靠。
内容的提问来源于stack exchange,提问作者chrisjarn
相关产品推荐
相关产品推荐

