Vue3实现Skeleton Loader:解决数据加载过快时闪烁问题
解决方案
核心思路是结合最小延迟阈值与图片加载完成事件,只有当两个条件都满足时才切换到真实内容。这样既避免快速加载时的骨架屏闪烁,又不会在慢加载场景下额外增加等待时间。
步骤1:调整状态变量
定义两个响应式变量,分别跟踪图片是否加载完成、是否过了最小延迟时间:
import { ref, onMounted } from 'vue'; const isLoaded = ref(false); const delayPassed = ref(false);
步骤2:修改加载逻辑
在onMounted中同时设置延迟定时器和图片加载监听:
onMounted(() => { // 最小延迟阈值,可根据视觉体验调整(建议150-200ms) const minDelay = 200; // 触发延迟标记 setTimeout(() => { delayPassed.value = true; }, minDelay); // 加载图片并监听完成事件 const img = new Image(getSrc('.jpg')); img.onload = () => { isLoaded.value = true; }; // 可选:处理图片加载失败的情况,避免骨架屏一直显示 img.onerror = () => { isLoaded.value = true; // 这里也可以添加错误状态,显示占位图 }; img.src = getSrc('.jpg'); });
步骤3:更新模板判断逻辑
只有当图片加载完成且过了最小延迟时间时,才显示真实内容;否则显示骨架屏(同时保留原有的pending状态判断):
<ItemCardSkeleton v-if="!pending || !(isLoaded && delayPassed)" /> <template v-else> <img class="card__image" :src="getSrc('.jpg')" :alt="recipe.alt" width="15.625rem" loading="lazy" /> <div class="card__content"> <h2 class="card__title">{{ recipe.title }}</h2> </div> </template>
逻辑说明
- 当图片加载耗时超过设定的最小延迟(比如网络慢):图片加载完成时,延迟标记已经为
true,会立刻切换到真实内容,无额外等待。 - 当图片加载耗时小于最小延迟(比如从缓存加载):会等够延迟时间再切换,避免骨架屏刚渲染就消失的闪烁问题。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

