Skeleton 骨架屏

在需要等待加载内容的位置设置一个骨架屏,某些场景下比 Loading 的视觉效果更好。

基础用法

基础的骨架效果。

Skeleton 骨架屏 - 图1

  1. <template>
  2. <el-skeleton />
  3. </template>

更多参数

可以配置骨架屏段落数量,以便更接近真实渲染效果。首行会被渲染一个长度 33% 的段首。

Skeleton 骨架屏 - 图2

  1. <el-skeleton :rows="6" />

动画效果

显示动画效果。

Skeleton 骨架屏 - 图3

  1. <el-skeleton :rows="6" animated />

自定义样式

ElementPlus 提供的排版模式有时候并不满足要求,当您想要用自己定义的模板时,可以通过一个具名 Slot 来自己设定模板。

我们提供了不同的模板单元可供使用,具体可选值请看 API 详细描述。 建议在描述模板的时候,尽量靠近真实的 DOM 结构,这样可以避免 DOM 高度差距引起的抖动。

Skeleton 骨架屏 - 图4

  1. <template>
  2. <el-skeleton style="width: 240px">
  3. <template slot="template">
  4. <el-skeleton-item variant="image" style="width: 240px; height: 240px;" />
  5. <div style="padding: 14px;">
  6. <el-skeleton-item variant="p" style="width: 50%" />
  7. <div
  8. style="display: flex; align-items: center; justify-items: space-between;"
  9. >
  10. <el-skeleton-item variant="text" style="margin-right: 16px;" />
  11. <el-skeleton-item variant="text" style="width: 30%;" />
  12. </div>
  13. </div>
  14. </template>
  15. </el-skeleton>
  16. </template>

Loading 状态

当 Loading 结束之后,我们往往需要显示真实的 UI,可以通过 loading 的值来控制是否显示真实的 DOM。然后通过 具名 Slot 来设置当 loading 结束之后需要展示的 UI。

Skeleton 骨架屏 - 图5

  1. <template>
  2. <div style="width: 240px">
  3. <p>
  4. <label style="margin-right: 16px;">切换 Loading</label>
  5. <el-switch v-model="loading" />
  6. </p>
  7. <el-skeleton style="width: 240px" :loading="loading" animated>
  8. <template slot="template">
  9. <el-skeleton-item
  10. variant="image"
  11. style="width: 240px; height: 240px;"
  12. />
  13. <div style="padding: 14px;">
  14. <el-skeleton-item variant="h3" style="width: 50%;" />
  15. <div
  16. style="display: flex; align-items: center; justify-items: space-between; margin-top: 16px; height: 16px;"
  17. >
  18. <el-skeleton-item variant="text" style="margin-right: 16px;" />
  19. <el-skeleton-item variant="text" style="width: 30%;" />
  20. </div>
  21. </div>
  22. </template>
  23. <template>
  24. <el-card :body-style="{ padding: '0px', marginBottom: '1px' }">
  25. <img
  26. src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"
  27. class="image"
  28. />
  29. <div style="padding: 14px;">
  30. <span>好吃的汉堡</span>
  31. <div class="bottom card-header">
  32. <span class="time">{{ currentDate }}</span>
  33. <el-button type="text" class="button">操作按钮</el-button>
  34. </div>
  35. </div>
  36. </el-card>
  37. </template>
  38. </el-skeleton>
  39. </div>
  40. </template>
  41. <script>
  42. export default {
  43. data () {
  44. return {
  45. loading: true,
  46. currentDate: '2021-06-01'
  47. }
  48. },
  49. }
  50. </script>

渲染多条数据

大多时候, 骨架屏都被用来渲染列表, 当我们需要在从服务器获取数据的时候来渲染一个假的 UI。利用 count 这个属性就能控制渲染多少条假的数据在页面上

请注意, 请尽可能的将 count 的大小保持在最小状态, 即使是假的 UI, DOM 元素多了之后, 照样会引起性能问题, 并且在骨架屏销毁时所消耗的时间也会更长(相对的)。

Skeleton 骨架屏 - 图6

  1. <template>
  2. <div style="width: 400px">
  3. <p>
  4. <el-button @click="setLoading">点我重新加载</el-button>
  5. </p>
  6. <el-skeleton style="width:400px" :loading="loading" animated :count="3">
  7. <template slot="template">
  8. <el-skeleton-item
  9. variant="image"
  10. style="width: 400px; height: 267px;"
  11. />
  12. <div style="padding: 14px;">
  13. <el-skeleton-item variant="h3" style="width: 50%;" />
  14. <div
  15. style="display: flex; align-items: center; justify-items: space-between; margin-top: 16px; height: 16px;"
  16. >
  17. <el-skeleton-item variant="text" style="margin-right: 16px;" />
  18. <el-skeleton-item variant="text" style="width: 30%;" />
  19. </div>
  20. </div>
  21. </template>
  22. <template>
  23. <el-card
  24. :body-style="{ padding: '0px', marginBottom: '1px' }"
  25. v-for="item in lists"
  26. :key="item.name"
  27. >
  28. <img :src="item.imgUrl" class="image multi-content" />
  29. <div style="padding: 14px;">
  30. <span>{{ item.name }}</span>
  31. <div class="bottom card-header">
  32. <span class="time">{{ currentDate }}</span>
  33. <el-button type="text" class="button">操作按钮</el-button>
  34. </div>
  35. </div>
  36. </el-card>
  37. </template>
  38. </el-skeleton>
  39. </div>
  40. </template>
  41. <script>
  42. export default {
  43. data() {
  44. return {
  45. loading: true,
  46. currentDate: '2021-06-01',
  47. lists: [],
  48. }
  49. },
  50. mounted() {
  51. this.loading = false
  52. this.lists = [
  53. {
  54. imgUrl:
  55. 'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
  56. name: '鹿',
  57. },
  58. {
  59. imgUrl:
  60. 'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
  61. name: '马',
  62. },
  63. {
  64. imgUrl:
  65. 'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
  66. name: '山狮',
  67. },
  68. ]
  69. },
  70. methods: {
  71. setLoading() {
  72. this.loading = true
  73. setTimeout(() => (this.loading = false), 2000)
  74. },
  75. },
  76. }
  77. </script>

防止渲染抖动

有的时候,API 的请求回来的特别快,往往骨架占位刚刚被渲染,真实的数据就已经回来了,用户的界面会突然一闪,此时为了避免这种情况,就需要通过 throttle 属性来避免这个问题。

Skeleton 骨架屏 - 图7

  1. <template>
  2. <div style="width: 240px">
  3. <p>
  4. <label style="margin-right: 16px;">切换 Loading</label>
  5. <el-switch v-model="loading" />
  6. </p>
  7. <el-skeleton
  8. style="width: 240px"
  9. :loading="loading"
  10. animated
  11. :throttle="500"
  12. >
  13. <template slot="template">
  14. <el-skeleton-item
  15. variant="image"
  16. style="width: 240px; height: 240px;"
  17. />
  18. <div style="padding: 14px;">
  19. <el-skeleton-item variant="h3" style="width: 50%;" />
  20. <div
  21. style="display: flex; align-items: center; justify-items: space-between; margin-top: 16px; height: 16px;"
  22. >
  23. <el-skeleton-item variant="text" style="margin-right: 16px;" />
  24. <el-skeleton-item variant="text" style="width: 30%;" />
  25. </div>
  26. </div>
  27. </template>
  28. <template>
  29. <el-card :body-style="{ padding: '0px', marginBottom: '1px'}">
  30. <img
  31. src="https://shadow.elemecdn.com/app/element/hamburger.9cf7b091-55e9-11e9-a976-7f4d0b07eef6.png"
  32. class="image"
  33. />
  34. <div style="padding: 14px;">
  35. <span>好吃的汉堡</span>
  36. <div class="bottom card-header">
  37. <span class="time">{{ currentDate }}</span>
  38. <el-button type="text" class="button">操作按钮</el-button>
  39. </div>
  40. </div>
  41. </el-card>
  42. </template>
  43. </el-skeleton>
  44. </div>
  45. </template>
  46. <script>
  47. export default {
  48. data() {
  49. return {
  50. loading: false,
  51. currentDate: '2021-06-01'
  52. }
  53. },
  54. }
  55. </script>

Skeleton Attributes

参数说明类型可选值默认值
animated是否使用动画booleantrue / falsefalse
count渲染多少个 template, 建议使用尽可能小的数字numberinteger1
loading是否显示 skeleton 骨架屏booleantrue / falsetrue
rows骨架屏段落数量number正整数4
throttle延迟占位 DOM 渲染的时间, 单位是毫秒number正整数0

Skeleton Item Attributes

参数说明类型可选值默认值
variant当前显示的占位元素的样式Enum(string)p / text / h1 / h3 / text / caption / button / image / circle / recttext

Skeleton Slots

namedescription
default用来展示真实 UI
template用来展示自定义占位符