骨架屏在 Vue 里怎么做到数据加载完自动隐藏?

Top丶丽萍 阅读 4

我用 Vue3 写了个商品列表页,想加个骨架屏提升体验。现在问题是:骨架屏显示出来了,但数据加载完成后不知道该怎么让它自动消失。我试过用 v-if 绑定 loading 状态,但有时候接口返回太快,骨架屏闪一下就没了,反而显得更卡。

目前我的结构大概是这样:

<template>
  <div v-if="loading">
    <!-- 骨架屏组件 -->
    <SkeletonItem v-for="i in 5" :key="i" />
  </div>
  <div v-else>
    <ProductItem v-for="item in products" :key="item.id" :data="item" />
  </div>
</template>

有没有办法让骨架屏至少显示 300ms,即使数据早就回来了?或者有更好的过渡方案?

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
Zz俊俊
Zz俊俊 Lv1
这个问题很简单,加个定时器延迟就行。

思路是:loading 变成 true 后,延迟 300ms 再显示骨架屏;loading 变成 false 时,立即隐藏真实内容,延迟 300ms 再隐藏骨架屏。这样不管接口多快,骨架屏都能保证至少显示 300ms。

直接上代码:

<template>
<div v-if="loading || skeletonVisible">
<SkeletonItem v-for="i in 5" :key="i" />
</div>
<div v-else>
<ProductItem v-for="item in products" :key="item.id" :data="item" />
</div>
</template>

<script setup>
import { ref, watch } from 'vue'

const loading = ref(false)
const skeletonVisible = ref(false)
const products = ref([])
let showTimer = null
let hideTimer = null

// 监听 loading 状态变化
watch(loading, (val) => {
if (val) {
// 开始加载,延迟显示骨架屏
clearTimeout(hideTimer)
showTimer = setTimeout(() => {
skeletonVisible.value = true
}, 300)
} else {
// 加载完成,立即隐藏骨架屏
clearTimeout(showTimer)
skeletonVisible.value = false
}
})

const fetchProducts = async () => {
loading.value = true
try {
const res = await fetch('/api/products')
products.value = await res.json()
} finally {
loading.value = false
}
}

fetchProducts()
</script>


核心逻辑就两点:

1. 用 skeletonVisible 单独控制骨架屏显示,loading 变 true 后等 300ms 才显示骨架屏
2. 模板里用 v-if="loading || skeletonVisible",这样 loading 变 false 时骨架屏还能保留 300ms

如果想更精细控制,可以把 300ms 做成配置项。

这个方案的好处是简单直接,不需要引入额外的过渡组件。复制过去改改接口地址就能用。
点赞
2026-03-18 22:00