前言
图片懒加载能减少服务器压力,比如一个前台展示网站,里面包含很多图片,如某宝它有很多商品的图片,但是用户不一定会浏览完整的网页,用户可能从某个分类的入口进入到了别的页面,那么就会造成加载了这么多的图片,压根没人看的境地;
介绍场景
一个页面里面用v-for遍历了一个带有12张图片的数组,一共12个标签
<div class="img-lazy p-6">
<img :src="item" v-for="item in images" :key="item" />
</div>
未使用懒加载时
页面一出来,滚动条在最顶部的时候,浏览器的网络进程会把img所需要的图片获取下来,然后交给渲染主线程去解析html,于是
同一时间
请求页面所有的图片;
使用懒加载后
使用图片懒加载后,只会加载在
视口
内的图片和缺省图片,当其它图片滚动到视口的时候才请求图片,如下图所示;
当然您还得考虑用户网络的状况,如果用户网络不佳,图片还没有请求到的时候可以使用缺省图代替;如下图所示
写vue3指令
此处用的是vueUse库来实现,详细的你可以查看vueUse
当然如果你不想用vueUse库,那么你也可以使用原生接口IntersectionObserver
import { useIntersectionObserver } from '@vueuse/core';
export default {
mounted(el: HTMLImageElement) {
//如果不是图片的话就不触发懒加载
if (!(el instanceof HTMLImageElement)) return;
// 把真正的地址暂存起来
const _src = el.src;
//设置个缺省图片
el.setAttribute('src', '/loading.png');
//如果你不想用vueuse,你也可以用原生的IntersectionObserver接口来实现
const { stop } = useIntersectionObserver(el, ([{ isIntersecting }]) => {
if (isIntersecting) {
//说明到视口中了,那就把真实的地址还原回去
el.setAttribute('src', _src);
//同时关闭Observer观察
stop();
}
});
},
};
全局注册指令
我是以插件的形式注册全局指令的,避免main.ts太多代码,看个人习惯你也可以其他写法,代码如下(示例):
import { App } from 'vue';//App是接口,做ts提示用
import lazyLoad from '/@/directives/lazyLoad';
export default {
install(Vue: App<Element>) {
Vue.directive('lazyLoad', lazyLoad);
},
};
在页面使用指令v-lazyLoad
<template>
<div class="img-lazy p-6">
<img :src="item" v-for="item in images" :key="item" v-lazyLoad />
</div>
</template>
<script setup name="imgLazy" lang="ts">
const images = reactive<string[]>([
'https://img-blog.csdnimg.cn/img_convert/29576b39b36e5c8681ee5f58409c0939.png',
'https://img-blog.csdnimg.cn/img_convert/ac3416110cce6fd635d27c248a0b4fcc.png',
'https://img-blog.csdnimg.cn/img_convert/b66edfe5bd07f16c3245a8270a97de06.png',
'https://img-blog.csdnimg.cn/img_convert/586dc56f36de6e74c6a8fd816043b828.png',
'https://img-blog.csdnimg.cn/img_convert/e0caff5972b2b620b0a1aacde5c33888.png',
'https://img-blog.csdnimg.cn/img_convert/6048591a7cf2c455aaf4ddc800029266.png',
'https://img-blog.csdnimg.cn/img_convert/64ba0169000f4650bb984fcc3622ba86.png',
'https://img-blog.csdnimg.cn/img_convert/639e2439552cab7c4b58d3d2e21c170d.png',
'https://img-blog.csdnimg.cn/img_convert/76351788d26e57a90e758004a9be4da2.png',
'https://img-blog.csdnimg.cn/img_convert/41dfef919cca8fc8666b5e0f4a86a08d.png',
'https://img-blog.csdnimg.cn/img_convert/96f3d6652819d02538ba9e5603df1815.png',
'https://img-blog.csdnimg.cn/img_convert/e2a5e7840655b3b51cb498712f9b924d.png',
]);
</script>
<style lang="less" scoped>
.img-lazy {
img {
@apply w-160 h-100 block mx-auto mb-6 rounded;
&:not([src]) {
opacity: 0;
}
}
}
</style>