Skip to content

Skeleton骨架屏 ​

在数据加载时提供占位效果

事先说明

关于 loading 的初始值,使用 true 无疑是最佳实践,这确保了后续访问字段的存在性

详细请见 渲染时机

INFO

基础用法示例为图片加载的占位操作

需要在 Skeleton 组件外部放一个不可见的图片 用于请求加载

当 loading 初始值为 true 时,因为 渲染时机 会使得 content插槽 里面的图片不会进行渲染

若不进行此操作 图片将永远无法加载

作用于Skeleton上的css无效

直接在 Skeleton 上设置样式是无效的,因为内部不会有任何元素去接受其样式

简而言之 Skeleton 组件不会也不应该对用户布局产生任何影响,它仅仅相对于一个标识符,以此完成骨架屏的效果,仅此而已

基础用法 ​

Skeleton 的使用不太同于其它框架,在 li-daisy 中 Skeleton 作为一个容器,然后借助 daisyUI 的 skeleton 去实现具体的骨架屏效果

例子中的 skeleton 是加了前缀的类名,具体类名取决于你项目中的 daisyUI 的配置

vue
<template>
  <div>
    <img class="sr-only" src="https://picsum.photos/300/300" @load="handleImgLoad" />

    <Skeleton :loading="loading" :delay="500">
      <template #content>
        <div class="space-y-3">
          <img
            v-for="i in 3"
            :key="i"
            class="mx-auto w-30 h-30 rounded-md"
            src="https://picsum.photos/300/300"
          />
        </div>
      </template>
      <template #skeleton>
        <div class="space-y-3">
          <div v-for="i in 3" :key="i" class="skeleton mx-auto w-30 h-30 rounded-md" />
        </div>
      </template>
    </Skeleton>
  </div>
</template>

<script setup lang="ts">
import { Skeleton } from 'li-daisy'
import { ref } from 'vue'

const loading = ref(true)

const handleImgLoad = () => {
  loading.value = false
}
</script>

设置遮罩 ​

有时为了让骨架屏更加有层次感,使用遮罩也是必要的

以下代码给出设置遮罩可行的方案

具体思路便是在 skeleton 插槽中使用一个 relative 的父级以及一个 absolute 的遮罩

遮罩层使用渐变背景 bg-gradient-to-t 从底部向顶部渐变,营造出内容逐渐淡出的视觉效果

通过 pointer-events-none 确保遮罩不会拦截用户的交互操作

z-10 确保遮罩在骨架屏内容之上显示

关于遮罩颜色选择:

  • 遮罩的过渡颜色应与骨架屏的背景色保持一致,通常使用 from-base-100 或 from-base-200
  • 如果骨架屏位于卡片或容器中,建议使用该容器的背景色类,如示例中的 from-base-100
  • 调整 from-60% 或 from-50% 的百分比值可以控制渐变的起始位置,数值越大渐变越靠下
  • 如果遮罩效果不明显,可以尝试增加不透明度或调整起始位置,如 from-base-100/90 from-40%
vue
<template>
  <div class="space-y-6">
    <Skeleton :loading="true" :delay="1000">
      <template #skeleton>
        <div class="relative border border-base-300 rounded-box bg-base-100 overflow-hidden">
          <ul class="list flex flex-col divide-y divide-base-300">
            <li v-for="i in 3" :key="i" class="p-4 space-y-3">
              <div class="grid items-center gap-4" style="grid-template-columns: auto 1fr auto">
                <div class="skeleton opacity-60 size-10 rounded-full"></div>

                <div class="space-y-2">
                  <div class="skeleton opacity-60 w-36 h-3 rounded-box"></div>
                  <div class="skeleton opacity-60 w-24 h-2 rounded-box"></div>
                </div>

                <div class="skeleton opacity-60 h-8 w-8 rounded-box"></div>
              </div>

              <div class="skeleton opacity-60 w-[50%] h-3 rounded-box"></div>
            </li>
          </ul>

          <div
            class="absolute bottom-0 left-0 right-0 top-32 pointer-events-none z-10 bg-gradient-to-t from-base-100 from-60% to-transparent"
          ></div>
        </div>
      </template>
    </Skeleton>
  </div>
</template>

<script setup lang="ts">
import { Skeleton } from 'li-daisy'
</script>

设置count ​

组件并未提供设置 count 的属性,而是建议手动去设置数量,因为此时可以确保布局的可控性

比如 上述例子 中就是使用简单的 v-for 去实现类似的效果

这样最大的好处就是可以极大统一 content 和 skeleton 插槽中的元素结构

设置delay ​

通过设置 delay 来设置延迟效果

当网络请求较快时,较容易出现闪烁的现象,通过设置这项,用户可以得到较好的视觉效果,默认值为 300(单位为ms)

渲染说明 ​

注意:由于骨架屏采用客户端条件渲染,爬虫访问时将获取到骨架屏占位符而非实际内容

如需 SEO 支持,建议在服务端预加载数据或采用其他 SSR 方案。

说明:skeleton 和 content 插槽基于 loading 值进行条件渲染(使用 v-if)

当 loading 为 false 时,骨架屏隐藏,内容显示

由于使用 v-if 因此可以安全地在 content 插槽中直接访问异步数据,无需额外的空值检查

API ​

Attributes ​

Skeleton ​

属性值说明类型默认值
loading加载状态boolean-
delay延迟时间/msnumber300
count骨架数目number1

Slots ​

Skeleton ​

插槽名说明
content实际要渲染的内容
skelton骨架屏内容