原理
存储图片的真实路径,把图片的真实路径绑定给一个以data开头的自定义属性data-url即可,页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片(没有请求就提高了性能)
<img data-src="imgs/1.jpg" alt="loading" class="img-item">
需要一个滚动事件,判断元素是否在浏览器窗口,一旦进入视口才进行加载,当滚动加载的时候,就把真正的图片url地址(也就是data-url里保存的值)赋值给src,并添加进img标签,就会去发送请求加载图片,真正实现了按需加载
js处理
offsetTop
<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>
getBoundingClientRect
getBoundingClientRect返回一个矩形对象,包含上下左右的偏移值
for (let i=0;i < imgs.length;i++) {
//计算方式和第一种方式不同
if (imgs[i].getBoundingClientRect().top < window.innerHeight) {
if(imgs[i].alt != 'loaded'){
imgs[i].src = imgs[i].getAttribute('data-src'); //将data-src属性值赋值给src
imgs[i].alt = 'loaded'
}
}
}
其中,getBoundingClientRect().top 为元素相对于窗口的位置;window.innerHeight 为当前窗口的高度;当元素对于窗口的位置小于当前窗口的高度时,那自然处于了窗口可视区了。
intersectionObserve
Intersection Observer 的作用是它能够观察可视窗口与目标元素产生的交叉区域。简单来说就是当用它观察我们的图片时,当图片出现或者消失在可视窗口,它都能知道并且会执行一个特殊的回调函数,我们就利用这个回调函数实现我们的操作。
<script>
let io = new IntersectionObserver(function (entires) {
//图片进入视口时就执行回调
entires.forEach(item => {
// 获取目标元素
let oImg = item.target
// console.log(item);
// 当图片进入视口的时候,就赋值图片的真实地址
if (item.intersectionRatio > 0 && item.intersectionRatio <= 1) {
oImg.setAttribute('src', oImg.getAttribute('data-url'))
}
})
})
Array.from(imgs).forEach(element => {
io.observe(element) //给每一个图片设置监听
});
</script>