Skip to content

Skeleton 骨架屏

在内容加载时显示骨架屏占位,提供视觉反馈。

名称分类说明类型默认值
animated? 风格是否显示闪烁动画booleantrue
animation? 风格动画风格:shimmer(扫描线)、pulse(闪烁)、dither(棋盘格溶解)'shimmer' | 'pulse' | 'dither''shimmer'
variant? 风格骨架屏变体形状'text' | 'circular' | 'rectangular' | 'rounded''rectangular'
width? 尺寸自定义宽度(数字为 px,字符串按原值)string | number
height? 尺寸自定义高度(数字为 px,字符串按原值)string | number
size? 尺寸骨架屏尺寸'large' | 'default' | 'small''default'
loading? 状态是否显示骨架屏booleantrue
rows? 内容文本变体的行数(仅 variant="text" 且 rows > 1 时生效)number1
default? 插槽加载完成后显示的内容

基础用法

显示不同宽度的骨架屏占位符。

<template>
  <div class="demo-skeleton">
    <px-skeleton />
    <px-skeleton width="75%" />
    <px-skeleton width="50%" />
  </div>
</template>

<style scoped>
.demo-skeleton {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
</style>

变体

通过 variant 属性切换骨架屏形状:rectangular(默认)、circularroundedtext

<template>
  <div class="demo-skeleton">
    <div class="demo-skeleton__item">
      <span class="demo-skeleton__label">rectangular</span>
      <px-skeleton variant="rectangular" width="120px" height="80px" />
    </div>
    <div class="demo-skeleton__item">
      <span class="demo-skeleton__label">circular</span>
      <px-skeleton variant="circular" />
    </div>
    <div class="demo-skeleton__item">
      <span class="demo-skeleton__label">rounded</span>
      <px-skeleton variant="rounded" width="120px" height="80px" />
    </div>
    <div class="demo-skeleton__item">
      <span class="demo-skeleton__label">text</span>
      <px-skeleton variant="text" width="200px" />
    </div>
  </div>
</template>

<style scoped>
.demo-skeleton {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 24px;
}
.demo-skeleton__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
.demo-skeleton__label {
  font-size: 12px;
  color: var(--vp-c-text-2);
  font-family: var(--px-font-family, monospace);
}
</style>

动画

通过 animated 属性控制动画开关。通过 animation 属性选择动画风格:shimmer(扫描线扫过)、pulse(两帧闪烁)或 dither(棋盘格溶解)。

<template>
  <div class="demo-skeleton">
    <div>
      <p class="demo-skeleton__label">shimmer (default)</p>
      <px-skeleton animation="shimmer" width="200px" />
    </div>
    <div>
      <p class="demo-skeleton__label">pulse</p>
      <px-skeleton animation="pulse" width="200px" />
    </div>
    <div>
      <p class="demo-skeleton__label">dither</p>
      <px-skeleton animation="dither" width="200px" />
    </div>
    <div>
      <p class="demo-skeleton__label">static</p>
      <px-skeleton :animated="false" width="200px" />
    </div>
  </div>
</template>

<style scoped>
.demo-skeleton {
  display: flex;
  gap: 32px;
  flex-wrap: wrap;
}
.demo-skeleton__label {
  margin-bottom: 8px;
  font-size: 12px;
  color: var(--vp-c-text-2);
  font-family: var(--px-font-family, monospace);
}
</style>

加载切换

通过 loading 属性控制骨架屏与实际内容的切换,内容通过默认插槽传入。

<template>
  <div class="demo-skeleton">
    <px-button @click="loading = !loading" size="small">
      {{ loading ? 'Show Content' : 'Show Skeleton' }}
    </px-button>
    <px-skeleton :loading="loading" width="300px">
      <p class="demo-skeleton__content">Content loaded successfully!</p>
    </px-skeleton>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const loading = ref(true);
</script>

<style scoped>
.demo-skeleton {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.demo-skeleton__content {
  margin: 0;
  font-family: var(--px-font-family, monospace);
}
</style>

多行文本

使用 variant="text" 配合 rows 属性渲染多行文本占位,最后一行自动缩短。

<template>
  <div class="demo-skeleton">
    <px-skeleton variant="text" :rows="3" width="300px" />
  </div>
</template>

<style scoped>
.demo-skeleton {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
</style>

尺寸

通过 size 属性设置预定义尺寸:largedefaultsmall

<template>
  <div class="demo-skeleton">
    <div class="demo-skeleton__item">
      <span class="demo-skeleton__label">large</span>
      <px-skeleton size="large" width="200px" />
    </div>
    <div class="demo-skeleton__item">
      <span class="demo-skeleton__label">default</span>
      <px-skeleton width="200px" />
    </div>
    <div class="demo-skeleton__item">
      <span class="demo-skeleton__label">small</span>
      <px-skeleton size="small" width="200px" />
    </div>
  </div>
</template>

<style scoped>
.demo-skeleton {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.demo-skeleton__item {
  display: flex;
  align-items: center;
  gap: 12px;
}
.demo-skeleton__label {
  font-size: 12px;
  color: var(--vp-c-text-2);
  font-family: var(--px-font-family, monospace);
  min-width: 60px;
}
</style>

自定义尺寸

通过 widthheight 属性精确控制尺寸。数字按像素处理,字符串按原值使用。

<template>
  <div class="demo-skeleton">
    <px-skeleton :width="250" :height="40" />
    <px-skeleton width="80%" height="3rem" />
    <px-skeleton variant="circular" :width="64" :height="64" />
  </div>
</template>

<style scoped>
.demo-skeleton {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
}
</style>