useFetch处于pending状态时骨架加载器不显示的问题求助
解决图片画廊骨架加载器不显示的问题
问题核心原因
useFetch的lazy: true配置:开启lazy后,请求不会自动触发,初始状态为idle而非pending,导致你写的v-if="status === 'pending'"永远无法匹配。- 骨架渲染时机错误:你的骨架是放在单个图片项的
v-if里,但初始imgList是空数组,v-for不会渲染任何项,骨架自然无法显示。
可行解决方案
方案1:调整useFetch配置,自动发起请求并渲染骨架
去掉lazy: true让请求自动执行,同时预设骨架数量(或根据预期图片数渲染),确保请求期间有骨架占位:
<template> <div class="grid grid-cols-4 gap-4"> <!-- 请求中渲染固定数量的骨架(比如8个) --> <div v-for="n in 8" v-if="status === 'pending'" class="w-full h-32 bg-gray-200 rounded-lg animate-pulse" /> <!-- 请求成功后渲染真实图片 --> <img v-for="item in imgList" :key="item.id" class="w-full cursor-pointer rounded-lg object-cover shadow-2xl" crossorigin="anonymous" :src="item.url" /> </div> </template> <script setup lang="ts"> const imgList = ref<Image[]>([]); const { apiBase } = useRuntimeConfig().public; // 移除lazy: true,让useFetch自动发起请求 const { data, status, error } = await useFetch<{ data: Image[] }>( `${apiBase}/get-images` ); // 监听数据变化,更新图片列表 watch(data, (newData) => { if (newData) { imgList.value = newData.data; } }); // 处理错误 if (error.value) { console.error('Error loading images: ', error.value); } </script>
方案2:保留lazy: true,手动触发请求
如果必须使用lazy模式,需要手动调用refetch()触发请求,确保状态进入pending:
<script setup lang="ts"> const imgList = ref<Image[]>([]); const { apiBase } = useRuntimeConfig().public; const { data, status, error, refetch } = useFetch<{ data: Image[] }>( `${apiBase}/get-images`, { lazy: true } ); // 手动触发请求 await refetch(); watch(data, (newData) => { if (newData) { imgList.value = newData.data; } }); if (error.value) { console.error('Error loading images: ', error.value); } </script>
额外:图片加载阶段的骨架优化
如果需要在图片本身加载完成前也显示骨架,可配合onload事件跟踪单张图片的加载状态:
<template> <div class="grid grid-cols-4 gap-4"> <div v-for="item in imgList" :key="item.id" class="relative"> <!-- 图片未加载完成时显示骨架 --> <div v-if="!loadedImages.has(item.id)" class="w-full h-32 bg-gray-200 rounded-lg animate-pulse" /> <img class="w-full cursor-pointer rounded-lg object-cover shadow-2xl" crossorigin="anonymous" :src="item.url" @load="loadedImages.add(item.id)" @error="loadedImages.add(item.id)" :style="loadedImages.has(item.id) ? 'display:block' : 'display:none'" /> </div> </div> </template> <script setup lang="ts"> const imgList = ref<Image[]>([]); const loadedImages = new Set<string | number>(); // ... 其他请求逻辑 </script>
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

