Element UI 通用图片骨架屏组件

近年来,骨架屏(Skeleton)逐渐成为一种流行的加载动画,其显著增强了用户等待过程中的体验。本文实现了 Vue.js + Element UI 的通用图片骨架屏组件。

感谢 @小灰灰 在研究过程中提供的帮助和创新,编写了组件的部分内容,作了大量重要的工作。

效果预览

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<template>
<el-skeleton
ref="root"
animated
:loading="loading"
>
<template #template>
<el-skeleton-item
:id="idName"
:class="className"
:style="{height: heightValue}"
variant="image"
/>
</template>
<template>
<img :id="idName" :class="className" :src="src" :alt="alt">
</template>
</el-skeleton>
</template>

<script>
export default {
name: "BaseLoadingImage",
props: {
className: {
type: String,
required: false,
},
idName: {
type: String,
required: false,
},
src: {
type: String,
required: true,
},
alt: {
type: String,
required: false,
},
height: {
type: String,
required: false,
},
},
data() {
return {
loading: true,
heightValue: this.height === undefined ? "200px" : this.height,
};
},
mounted() {
if (this.height === undefined) {
this.heightValue = (this.$refs.root.$el.clientWidth / 16 * 9) + "px";
}
let img = new Image();
img.onload = () => {
this.loading = false;
};
img.src = this.src;
},
};
</script>

使用

使用时只需传递相应参数即可:

1
<loading-image src="src.webp"></loading-image>

若需要修改图片的样式,只需传递 classid 从外部使用 v-deep 设置 css 即可。

1
<loading-image class-name="class-1" id-name="id-1" src="src.webp"></loading-image>
1
2
3
4
5
6
7
::v-deep .class-1 {
width: 100%;
}

::v-deep #id-1 {
border-radius: 1rem;
}

原理解析

该组件主要由两大功能组成,一是加载图片并切换骨架屏显示,二是智能高度调整。

加载功能

由于默认 loadingtrue,所以 <img> 并不会显示,浏览器也不会请求图片资源。我们在 mounted 时使用 js 请求图片资源。当图片加载完成后,将 loading 设置为 false 且更新 <img>

1
2
3
4
5
let img = new Image();
img.onload = () => {
this.loading = false;
};
img.src = this.src;

智能高度调整

骨架的高度遵循以下规则:

  1. 若传递了高度参数,使用参数设置高度;
  2. mounte 之前使用 200px 作为默认高度;
  3. mounte 之后获取宽度,以 16:9 计算默认高度。

References

  1. Skeleton 骨架屏. Element. [2022-11-16]. (原始内容存档于2022-11-16).

Element UI 通用图片骨架屏组件
https://blog.zhanganzhi.com/zh-CN/2022/11/92e7bb97253e/
作者
Andy Zhang
发布于
2022年11月16日
许可协议