Appearance
Skeleton 骨架屏
在内容就绪前展示与真实布局接近的占位块,适合文章、成员列表和图片卡片的首次加载。
基础用法与占位形状
text
p
h1
h2
h3
caption
button
circle
rect
image
<template>
<div class="skeleton-basic-demo">
<div class="au-doc-row">
<AuButton :selected="animated" @click="animated = !animated">{{ animated ? '关闭动画' : '开启动画' }}</AuButton>
</div>
<AuSkeleton :rows="3" :animated="animated" />
<div class="skeleton-basic-demo__variants">
<div v-for="variant in variants" :key="variant" class="skeleton-basic-demo__variant">
<span>{{ variant }}</span>
<AuSkeletonItem :variant="variant" :animated="animated" />
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { AuButton, AuSkeleton, AuSkeletonItem } from 'aurora-plus';
const animated = ref(false);
const variants = ['text', 'p', 'h1', 'h2', 'h3', 'caption', 'button', 'circle', 'rect', 'image'];
</script>
<style scoped>
.skeleton-basic-demo { display: grid; gap: 20px; width: 100%; }
.skeleton-basic-demo__variants { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 16px; }
.skeleton-basic-demo__variant { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; min-width: 0; font-size: 12px; color: var(--au-color-text-secondary); }
</style>自定义模板与内容切换
<template>
<div class="skeleton-template-demo">
<div class="au-doc-row">
<AuButton :selected="loading" @click="loading = !loading">{{ loading ? '显示内容' : '显示骨架屏' }}</AuButton>
</div>
<AuSkeleton :loading="loading" :count="members.length" animated>
<template #template="{ index }">
<div class="skeleton-template-demo__row">
<AuSkeletonItem variant="circle" :width="32" :height="32" />
<div class="skeleton-template-demo__details">
<AuSkeletonItem :width="index === 0 ? '42%' : '55%'" />
<AuSkeletonItem variant="caption" width="76%" />
</div>
</div>
</template>
<template #default>
<div class="skeleton-template-demo__list">
<div v-for="member in members" :key="member.name" class="skeleton-template-demo__row">
<span class="skeleton-template-demo__avatar">{{ member.name.slice(0, 1) }}</span>
<div class="skeleton-template-demo__details">
<span class="skeleton-template-demo__name">{{ member.name }}</span>
<span class="skeleton-template-demo__description">{{ member.description }}</span>
</div>
</div>
</div>
</template>
</AuSkeleton>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { AuButton, AuSkeleton, AuSkeletonItem } from 'aurora-plus';
const loading = ref(true);
const members = [
{ name: '林晓', description: '负责组件交互设计' },
{ name: '陈远', description: '负责主题与交互体验' },
{ name: '苏宁', description: '负责使用指南与示例' },
];
</script>
<style scoped>
.skeleton-template-demo { display: grid; gap: 16px; width: 100%; }
.skeleton-template-demo__list { display: grid; gap: 16px; }
.skeleton-template-demo__row { display: flex; align-items: center; gap: 12px; min-height: 34px; }
.skeleton-template-demo__details { display: grid; gap: 8px; flex: 1; min-width: 0; }
.skeleton-template-demo__avatar { display: grid; place-items: center; width: 32px; height: 32px; flex-shrink: 0; border: 1px solid var(--au-color-border-default); border-radius: 50%; font-size: 14px; }
.skeleton-template-demo__name { font-size: 14px; line-height: 14px; }
.skeleton-template-demo__description { font-size: 12px; line-height: 12px; color: var(--au-color-text-secondary); }
</style>延迟显示与隐藏
内容已就绪。短于 300ms 的请求不会显示占位块。
<template>
<div class="skeleton-throttle-demo">
<div class="au-doc-row">
<AuButton @click="reload(100)">模拟快速请求(100ms)</AuButton>
<AuButton @click="reload(1200)">模拟普通请求(1200ms)</AuButton>
</div>
<div class="skeleton-throttle-demo__content">
<AuSkeleton :loading="loading" :throttle="{ leading: 300, trailing: 200 }" :rows="2" animated>
<template #default>
<div class="skeleton-throttle-demo__result">内容已就绪。短于 300ms 的请求不会显示占位块。</div>
</template>
</AuSkeleton>
</div>
</div>
</template>
<script setup>
import { onBeforeUnmount, ref } from 'vue';
import { AuButton, AuSkeleton } from 'aurora-plus';
const loading = ref(false);
let timer;
function reload(duration) {
clearTimeout(timer);
loading.value = true;
timer = setTimeout(() => { loading.value = false; }, duration);
}
onBeforeUnmount(() => clearTimeout(timer));
</script>
<style scoped>
.skeleton-throttle-demo { display: grid; gap: 16px; width: 100%; }
.skeleton-throttle-demo__content { min-height: 72px; }
.skeleton-throttle-demo__result { display: flex; align-items: center; min-height: 72px; font-size: 14px; color: var(--au-color-text-default); }
</style>AuSkeleton 属性
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| loading | 是否正在加载 | boolean | true |
| animated | 子占位块是否启用呼吸动画 | boolean | false |
| rows | 默认模板的段落行数,不含标题;非负整数 | number | 3 |
| count | 占位模板重复数量;正整数 | number | 1 |
| throttle | 延迟显示,或分别控制显隐,单位 ms | number / | 0 |
AuSkeleton 插槽
| 插槽 | 说明 | 参数 |
|---|---|---|
| template | 加载期间重复渲染的占位模板 | { index: number },从 0 开始 |
| default | 加载结束且隐藏延迟完成后的业务内容 | — |
AuSkeletonItem 属性
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| variant | 占位形状 | text / p / h1 / h2 / h3 / caption / button / circle / rect / image | text |
| width | 宽度;数字为 px,字符串为 CSS 长度 | number / string | 由形状决定 |
| height | 高度;数字为 px,字符串为 CSS 长度 | number / string | 由形状决定 |
| animated | 覆盖容器的动画设置 | boolean | 跟随最近的 AuSkeleton,独立使用时为 false |