前言
why?
懒加载:访问一个页面,可视区域的图片优先显示, 而不是一次性加载所有图片,随可视
区域增加,再发送图片请求,避免打开网页时加载过多资源。使页面加载速度快、减轻
服务器的压力、节省流量。
实现方式:
1、监听页面监听scroll事件滚动(不推荐)
2、使用:Intersection Observer API
3、插件vue3-lazy实现(支持vue3和ts)(vue2.x可以使用vue-lazyload)
监听scroll事件
当图片距离视窗顶部的距离大于浏览器窗口显示区的高度时,图片不可见,反之可见
const images = document.querySelectorAll("img");
window.addEventListener("scroll", e => {
// 先判断每张图片的位置是否在可视区域
images.forEach(image => {
const imageTop = image.getBoundingClientRect().top;
if (imageTop < window.innerHeight) {
const data_src = image.getAttribute("data-src");
image.setAttribute("src", data_src);
}
console.log("scroll");
});
});
这种方法会多次触发,不推荐使用,推荐使用下面的IntersectionObserver
使用:Intersection Observer API
当一个IntersectionObserver对象被创建时,其被配置为监听根中一段给定比例的可见区域。
一旦IntersectionObserver被创建,则无法更改其配置,所以一个给定的观察者对象只能用来监听可见区域的特定变化值;
然而,你可以在同一个观察者对象中配置监听多个目标元素。
<template>
<main class="container">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/home1/ddstep2.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/home1/ddstep2.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/home1/ddstep2.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/home1/ddstep2.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/home1/ddstep2.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/home1/ddstep2.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/home1/ddstep2.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/home1/ddstep2.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/home1/ddstep2.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/index/banner.png">
<img data-src="/src/assets/images/home1/ddstep2.png">
<img data-src="/src/assets/images/index/banner.png">
</main>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue' // introjs主题
// 传给IntersectionObserver的回调函数
// 在目标元素能看见时触发一次,目标元素看不见了时再触发一次
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const image = entry.target;
const data_src:any = image.getAttribute('data-src');
console.log('src', data_src)
image.setAttribute('src', data_src);
// 图片被加载后取消观察
observer.unobserve(image);
}
});
});
onMounted(() => {
const images = document.querySelectorAll('img');
images.forEach((image) => {
observer.observe(image);
});
})
</script>
<style scoped lang="scss">
.container{
font-family: 'Helvetica Neue';
font-style: normal;
font-weight: 500;
font-size: 24px;
line-height: 32px;
color: #171B23;
.header{
color: #434C5B;
font-family: 'PingFang SC';
}
img{
width: 200px;
height: 100px;
}
}
</style>
插件 vue3-lazy
安装
npm install vue3-lazy -S
main.ts中全局引入
import { createApp } from 'vue'
import App from './App.vue'
import lazyPlugin from 'vue3-lazy'
createApp(App).use(lazyPlugin,{
loading: '@/assets/images/default.png', //图⽚加载中时显⽰的默认图⽚
error: '@/assets/images/error.png' //图⽚加载失败后显⽰的图⽚
})
组件使用
<img v-lazy="'/src/assets/images/index/banner.png'">