小白尝试实现了一款vue3的懒加载图片组件,借助自定义指令实现,有更好的建议欢迎提出
导入loading动画
<template>
<div class="loader">
<div class="loader-square" style="--i:0s"></div>
<div class="loader-square" style="--i:-1.4285714286s"></div>
<div class="loader-square" style="--i:-2.8571428571s"></div>
<div class="loader-square" style="--i:-4.2857142857s"></div>
<div class="loader-square" style="--i:-5.7142857143s"></div>
<div class="loader-square" style="--i:-7.1428571429s"></div>
<div class="loader-square" style="--i:-8.5714285714s"></div>
</div>
</template>
<style lang="scss" scoped>
.loader {
position: relative;
width: 96px;
height: 96px;
transform: rotate(45deg);
&-square {
position: absolute;
top: 0;
left: 0;
width: 28px;
height: 28px;
margin: 2px;
border-radius: 0px;
background: white;
background-size: cover;
background-position: center;
background-attachment: fixed;
animation: square-animation 10s ease-in-out infinite both;
animation-delay: var(--i);
}
}
@keyframes square-animation {
0% {
left: 0;
top: 0;
}
10.5% {
left: 0;
top: 0;
}
12.5% {
left: 32px;
top: 0;
}
23% {
left: 32px;
top: 0;
}
25% {
left: 64px;
top: 0;
}
35.5% {
left: 64px;
top: 0;
}
37.5% {
left: 64px;
top: 32px;
}
48% {
left: 64px;
top: 32px;
}
50% {
left: 32px;
top: 32px;
}
60.5% {
left: 32px;
top: 32px;
}
62.5% {
left: 32px;
top: 64px;
}
73% {
left: 32px;
top: 64px;
}
75% {
left: 0;
top: 64px;
}
85.5% {
left: 0;
top: 64px;
}
87.5% {
left: 0;
top: 32px;
}
98% {
left: 0;
top: 32px;
}
100% {
left: 0;
top: 0;
}
}
</style>
搭建自定义图片懒加载组件
基本结构
<template>
<div class="img">
<div class="img-loading">
<Loading></Loading>
</div>
<img class="fade" />
</div>
</template>
<script setup >
//导入loading组件
import Loading from './Loading.vue';
</script>
<style lang="scss" scoped >
.img{
position: relative;
width: 100%;
&-loading{
position: absolute;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
img{
width: 100%;
height: 100%;
object-fit: cover;
}
.fade{
visibility: hidden;
}
.hide{
display: none;
}
}
</style>
设置.fade与.hide目的是为了前期隐藏图片,后续展示图片和隐藏loading
编写自定义指令
function DefineLazy(app) {
app.directive("lazy", {
mounted(el, binding) {
const observer = new IntersectionObserver(([{ intersectionRatio }]) => {
if (intersectionRatio > 0) {
const img = el.children[1];
const loading = el.children[0];
img.src = binding.value;
img.onload = () => {
img.classList.remove("fade");
loading.classList.add("hide");
};
observer.unobserve(el);
}
});
observer.observe(el);
},
});
}
export default DefineLazy;
这里借助IntersectionObserver中的intersectionRatio来判断是否已滚动页面到图片的相交处,从而添加链接展示图片,以此实现图片懒加载
其中,使用load事件将图片展示,loading去除
Vue中use自定义指令,实现注册
import { createApp } from 'vue'
import App from './App.vue'
import lazy from './hooks/lazy'
createApp(App)
.use(lazy)
.mount('#app')
正式使用
<Img v-lazy="val.src"/>
val.src为图片链接地址