骷髅
加载数据时,如果您需要为最终用户提供丰富的视觉和交互体验,您可以选择skeleton。
基本用法
基本骨架。
<template>
<el-skeleton />
<br />
<el-skeleton style="--el-skeleton-circle-size: 100px">
<template #template>
<el-skeleton-item variant="circle" />
</template>
</el-skeleton>
</template>
可配置的行
你可以自己配置行号,为了更精确的渲染效果,实际渲染的行号总是比给定的行号多1行,这是因为我们渲染的标题行宽度是其他行的33%。
动画
我们提供了一个开关标志,指示是否显示加载动画,称为animated,当为true时,el-skeleton的所有子节点都会显示动画
定制模板
Element Plus 仅提供最常见的模板,有时这可能会出现问题,因此您有一个名为 template 的插槽来完成这项工作。
我们还提供了不同类型的骨架单元供您选择,有关更多详细信息,请向下滚动到本页底部查看 API 说明。另外,在构建您自己的自定义骨架结构时,您应该将它们构造得尽可能接近真实的 DOM,从而避免由于高度差而导致 DOM 弹跳。
<template>
<el-skeleton style="width: 240px">
<template #template>
<el-skeleton-item variant="image" style="width: 240px; height: 240px" />
<div style="padding: 14px">
<el-skeleton-item variant="p" style="width: 50%" />
<div
style="
display: flex;
align-items: center;
justify-items: space-between;
"
>
<el-skeleton-item variant="text" style="margin-right: 16px" />
<el-skeleton-item variant="text" style="width: 30%" />
</div>
</div>
</template>
</el-skeleton>
</template>
加载状态
当Loading结束时,我们总是需要向最终用户展示带有数据的真实UI。通过属性 loading 我们可以控制是否显示 DOM。您还可以使用槽 default 来构造真实的 DOM 元素。
<template>
<el-space direction="vertical" alignment="flex-start">
<div>
<label style="margin-right: 16px">Switch Loading</label>
<el-switch v-model="loading" />
</div>
<el-skeleton style="width: 240px" :loading="loading" animated>
<template #template>
<el-skeleton-item variant="image" style="width: 240px; height: 240px" />
<div style="padding: 14px">
<el-skeleton-item variant="h3" style="width: 50%" />
<div
style="
display: flex;
align-items: center;
justify-items: space-between;
margin-top: 16px;
height: 16px;
"
>
<el-skeleton-item variant="text" style="margin-right: 16px" />
<el-skeleton-item variant="text" style="width: 30%" />
</div>
</div>
</template>
<template #default>
<el-card :body-style="{ padding: '0px', marginBottom: '1px' }">
<img
src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"
class="image"
/>
<div style="padding: 14px">
<span>Delicious hamburger</span>
<div class="bottom card-header">
<div class="time">{{ currentDate }}</div>
<el-button text class="button">Operation button</el-button>
</div>
</div>
</el-card>
</template>
</el-skeleton>
</el-space>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(true)
const currentDate = new Date().toDateString()
</script>
渲染数据列表
大多数时候,骨架用作渲染尚未从服务器获取的数据列表的指示器,然后我们需要无缘无故地创建一个骨架列表,使其看起来像是正在加载,使用 count 属性,您可以控制需要渲染到浏览器的数量。
TIP
我们不建议向浏览器渲染大量假UI,它仍然会导致性能问题,而且破坏骨架的成本也会更长。保持 count 尽可能小,以获得更好的用户体验。
<template>
<el-space style="width: 100%" fill>
<div>
<el-button @click="setLoading">Click me to reload</el-button>
</div>
<el-skeleton
style="display: flex; gap: 8px"
:loading="loading"
animated
:count="3"
>
<template #template>
<div style="flex: 1">
<el-skeleton-item variant="image" style="height: 240px" />
<div style="padding: 14px">
<el-skeleton-item variant="h3" style="width: 50%" />
<div
style="
display: flex;
align-items: center;
justify-items: space-between;
margin-top: 16px;
height: 16px;
"
>
<el-skeleton-item variant="text" style="margin-right: 16px" />
<el-skeleton-item variant="text" style="width: 30%" />
</div>
</div>
</div>
</template>
<template #default>
<el-card
v-for="item in lists"
:key="item.name"
:body-style="{ padding: '0px', marginBottom: '1px' }"
>
<img
:src="item.imgUrl"
class="image multi-content"
style="max-width: 100%"
/>
<div style="padding: 14px">
<span>{{ item.name }}</span>
<div class="bottom card-header">
<div class="time">{{ currentDate }}</div>
<el-button text class="button">Operation button</el-button>
</div>
</div>
</el-card>
</template>
</el-skeleton>
</el-space>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
interface ListItem {
imgUrl: string
name: string
}
const loading = ref(true)
const lists = ref<ListItem[]>([])
const currentDate = new Date().toDateString()
const setLoading = () => {
loading.value = true
setTimeout(() => {
loading.value = false
}, 2000)
}
onMounted(() => {
loading.value = false
lists.value = [
{
imgUrl:
'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
name: 'Deer',
},
{
imgUrl:
'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
name: 'Horse',
},
{
imgUrl:
'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
name: 'Mountain Lion',
},
]
})
</script>
避免渲染弹跳。
有时API响应非常快,当这种情况发生时,骨架刚刚渲染到DOM,然后它需要切换回真实的DOM,这会导致突然的华丽。为了避免这种情况,您可以使用 throttle 属性。
TIP
从 2.8.8 开始,throttle 属性支持两个值:number 和 object。当传递一个number时,相当于{leading: xxx},控制骨架屏显示的节流。当然也可以通过{trailing: xxx}来控制骨架屏消失的节流

<template>
<el-space direction="vertical" alignment="flex-start">
<div>
<label style="margin-right: 16px">Switch Loading</label>
<el-switch v-model="loading" />
</div>
<el-skeleton
style="width: 240px"
:loading="loading"
animated
:throttle="500"
>
<template #template>
<el-skeleton-item variant="image" style="width: 240px; height: 265px" />
<div style="padding: 14px">
<el-skeleton-item variant="h3" style="width: 50%" />
<div
style="
display: flex;
align-items: center;
justify-items: space-between;
margin-top: 16px;
height: 16px;
"
>
<el-skeleton-item variant="text" style="margin-right: 16px" />
<el-skeleton-item variant="text" style="width: 30%" />
</div>
</div>
</template>
<template #default>
<el-card :body-style="{ padding: '0px', marginBottom: '1px' }">
<img
src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"
class="image"
/>
<div style="padding: 14px">
<span>Delicious hamburger</span>
<div class="bottom card-header">
<div class="time">{{ currentDate }}</div>
<el-button text class="button">operation button</el-button>
</div>
</div>
</el-card>
</template>
</el-skeleton>
</el-space>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const currentDate = new Date().toDateString()
</script>
初始渲染加载2.8.8
当loading初始值为true时,可以设置throttle: {initVal: true, leading: xxx}来控制初始骨架屏立即显示,不限流。
<template>
<el-space direction="vertical" alignment="flex-start">
<div>
<label style="margin-right: 16px">Switch Loading</label>
<el-switch v-model="loading" />
</div>
<el-skeleton
style="width: 240px"
:loading="loading"
animated
:throttle="{ leading: 500, initVal: true }"
>
<template #template>
<el-skeleton-item variant="image" style="width: 240px; height: 265px" />
<div style="padding: 14px">
<el-skeleton-item variant="h3" style="width: 50%" />
<div
style="
display: flex;
align-items: center;
justify-items: space-between;
margin-top: 16px;
height: 16px;
"
>
<el-skeleton-item variant="text" style="margin-right: 16px" />
<el-skeleton-item variant="text" style="width: 30%" />
</div>
</div>
</template>
<template #default>
<el-card :body-style="{ padding: '0px', marginBottom: '1px' }">
<img
src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"
class="image"
/>
<div style="padding: 14px">
<span>Delicious hamburger</span>
<div class="bottom card-header">
<div class="time">{{ currentDate }}</div>
<el-button text class="button">operation button</el-button>
</div>
</div>
</el-card>
</template>
</el-skeleton>
</el-space>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(true)
const currentDate = new Date().toDateString()
</script>
切换显示/隐藏而不撕裂弹跳 2.8.8
TIP
您可以设置throttle: {initVal: true, leading: xxx, trailing: xxx}来控制骨架效果的初始显示,让切换加载状态时骨架的过渡更加平滑。
有时您希望在加载切换显示或隐藏时更流畅地渲染业务组件。您可以使用设置 throttle: {leading: xxx, trailing:xxx} 来控制渲染弹跳。
<template>
<el-space direction="vertical" alignment="flex-start">
<div>
<label style="margin-right: 16px">Switch Loading</label>
<el-switch v-model="loading" />
</div>
<el-skeleton
style="width: 240px"
:loading="loading"
animated
:throttle="{ leading: 500, trailing: 500, initVal: true }"
>
<template #template>
<el-skeleton-item variant="image" style="width: 240px; height: 265px" />
<div style="padding: 14px">
<el-skeleton-item variant="h3" style="width: 50%" />
<div
style="
display: flex;
align-items: center;
justify-items: space-between;
margin-top: 16px;
height: 16px;
"
>
<el-skeleton-item variant="text" style="margin-right: 16px" />
<el-skeleton-item variant="text" style="width: 30%" />
</div>
</div>
</template>
<template #default>
<el-card :body-style="{ padding: '0px', marginBottom: '1px' }">
<img
src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"
class="image"
/>
<div style="padding: 14px">
<span>Delicious hamburger</span>
<div class="bottom card-header">
<div class="time">{{ currentDate }}</div>
<el-button text class="button">operation button</el-button>
</div>
</div>
</el-card>
</template>
</el-skeleton>
</el-space>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
const loading = ref(false)
const currentDate = new Date().toDateString()
</script>
骨架 API
骨骼属性
| 名称 | 描述 | 类型 | 默认 |
|---|---|---|---|
| 动画 | 是否显示动画 | 布尔值 | 假 |
| 计数 | 有多少假项目渲染到 DOM | 数字 | 1 |
| 加载 | 是否显示真实的DOM | 布尔值 | 假 |
| 行 | 行号,仅在未给出模板槽时有用 | 数字 | 3 |
| 油门 | 渲染延迟(以毫秒为单位)。数字代表延迟显示,也可以设置延迟隐藏,例如{ leading: 500, trailing: 500 }。当需要控制加载初始值时,可以设置{ initVal: true } | 数字 / 对象 | 0 |
骷髅槽位
| 名称 | 描述 | 类型 |
|---|---|---|
| 默认 | 真实渲染 DOM | 对象 |
| 模板 | 内容作为渲染骨架模板 | 对象 |
骨架项 API
SkeletonItem 属性
| 名称 | 描述 | 类型 | 默认 |
|---|---|---|---|
| 变体 | 当前渲染骨架类型 | 枚举 | 文字 |