第一种方式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.imgs{
display: flex;
flex-direction: column;
text-align: center;
width: 500px;
}
.img-item{
height:600px;
width: 400px;
margin: 10px;
}
</style>
</head>
<body>
<div class="imgs">
<img data-src="imgs/1.jpg" alt="loading" class="img-item">
<img data-src="imgs/2.jpg" alt="loading" class="img-item">
<img data-src="imgs/3.jpg" alt="loading" class="img-item">
<img data-src="imgs/4.jpg" alt="loading" class="img-item">
<img data-src="imgs/5.jpg" alt="loading" class="img-item">
<img data-src="imgs/6.jpg" alt="loading" class="img-item">
<img data-src="imgs/7.jpg" alt="loading" class="img-item">
<img data-src="imgs/8.jpg" alt="loading" class="img-item">
<img data-src="imgs/9.jpg" alt="loading" class="img-item">
<img data-src="imgs/10.jpg" alt="loading" class="img-item">
<img data-src="imgs/11.jpg" alt="loading" class="img-item">
<img data-src="imgs/12.jpg" alt="loading" class="img-item">
<img data-src="imgs/13.jpg" alt="loading" class="img-item">
</div>
</body>
<script>
let imgs = document.querySelectorAll('img');
let lazyload = function(){
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop; //获取浏览器滚动高度
let height = window.innerHeight; //获取浏览器可视高度
for(let i=0;i < imgs.length;i++){
//如果元素距离文档顶部的高度小于浏览器的滚动高度加浏览器的可视高度,则需要加载
if(imgs[i].offsetTop < scrollTop + height ){ //imgs[i].offsetTop 距离文档顶部的高度
//性能优化 进行判断 已经加载的不会再进行加载
if(imgs[i].alt != 'loaded'){
imgs[i].src = imgs[i].getAttribute('data-src'); //将data-src属性值赋值给src
imgs[i].alt = 'loaded'
}
}
}
}
//调用懒加载函数,加一个防抖函数
function throttle(method,delay){
let timer = null;
return function(){
clearTimeout(timer);
timer=setTimeout(function(){
method()
},delay);
}
}
window.onscroll = throttle(lazyload,200);
</script>
</html>
第二种方式:
第二种方式其实和第一种差不多,只是计算图片是否在可视区方式不同,重复的部分就省略了,如下:
window.addEventListener("scroll", (e) => {
ergodic();
});
function ergodic() {
for (let i of images) {
//计算方式和第一种方式不同
if (i.getBoundingClientRect().top < window.innerHeight) {
let trueSrc = i.getAttribute("data-src");
i.setAttribute("src", trueSrc);
}
}
}
ergodic();
第三种方式(优):
其实上面两种方式已经大致实现懒加载,但是,它们都有一个缺点,就是一当发生滚动事件时,就发生了大量的循环和判断操作判断图片是否可视区里。这自然是不太好的,那是否有解决方法。这里就引入了一个叫 Intersection Observer 观察器接口,它是是浏览器原生提供的构造函数,使用它能省到大量的循环和判断。当然它的兼容可能不太好,看情况使用。
Intersection Observer 是什么呢?这个构造函数的作用是它能够观察可视窗口与目标元素产生的交叉区域。简单来说就是当用它观察我们的图片时,当图片出现或者消失在可视窗口,它都能知道并且会执行一个特殊的回调函数,我们就利用这个回调函数实现我们的操作。概念枯燥难懂,直接看下面例子:
var images = document.getElementsByTagName("img");
function callback(entries) {
for (let i of entries) {
if (i.isIntersecting) {
let img = i.target;
let trueSrc = img.getAttribute("data-src");
img.setAttribute("src", trueSrc);
observer.unobserve(img);
}
}
}
const observer = new IntersectionObserver(callback);
for (let i of images) {
observer.observe(i);
}