在一个网站含有大量的图片,我们在进入一个页面的时候如果一下子全部加载完毕,就会造成很大的资源浪费,而懒加载就是用户浏览到哪里,就加载哪里的图片,这样就可以减少资源的浪费了。
1.懒加载的实现原理
一个img标签如果没有src属性,浏览器就不会发起请求,所以我们在图片没有进入可视区域之前就不会给img标签赋值src属性
2.懒加载的实现方式
(1)使用scrollTop/innerHeight/offsetTop
window.innerHeight:浏览器可视区域高度
document.body.scrollTop || document.documentElement.scrollTop:浏览器滚动条滚过高度(考虑到了兼容)
img.offsetTop:元素距文档顶部的高度
图片的加载条件:img.offsetTop < window.innerHeight + document.body.scrollTop;
基础代码:
<script type="text/javascript">
var imgs = document.querySelectorAll('img');
window.onscroll = function(){
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
var winTop = window.innerHeight;
for(var i=0;i < imgs.length;i++){
if(imgs[i].offsetTop < scrollTop + winTop ){
imgs[i].src = imgs[i].getAttribute('data-src');
}
}
}
</script>
但是我们需要优化一下基础代码,为了防止重复加载,我们需要对基础代码中的函数使用函数节流
<script type="text/javascript">
var imgs = document.querySelectorAll('img');
var lazyload = function(){
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
var winTop = window.innerHeight;
for(var i=0;i < imgs.length;i++){
if(imgs[i].offsetTop < scrollTop + winTop ){
imgs[i].src = imgs[i].getAttribute('data-src');
}
}
}
function throttle(method,delay){
var timer = null;
return function(){
var context = this, args=arguments;
clearTimeout(timer);
timer=setTimeout(function(){
method.apply(context,args);
},delay);
}
}
window.onscroll = throttle(lazyload,200);
</script>
(2)使用IntersectionObserver方法
基本知识
var io = new IntersectionObserver(callback, option);
//开始观察
io.observe(document.getElementById('example'));
//停止观察
io.unobserve(element);
// 关闭观察器
io.disconnect();
callback是可见性变化时的回调函数,option是配置对象。这个构造函数的返回值是一个观察器实例。构造函数的返回值是一个观察器实例,实例的observe方法可以指定观察哪个DOM节点。
上面代码中,observe的参数是一个DOM节点对象。如果要观察多个节点,就要多次调用这个方法。callback函数的参数(entries)是一个数组,每个成员都是一个IntersectionObserverEntry对象。举例来说,如果同时有两个被观察的对象的可见性发生变化,entries数组就会有两个成员。intersectionRatio:目标元素的可见比例,完全可见时为1,完全不可见时小于等于0。
完整代码
<script type="text/javascript">
//获取观察器实例 changes是被观察的对象数组
var observer = new IntersectionObserver(function(changes){
console.log(changes);
changes.forEach(function(index,item){
if(item.intersectionRatio > 0 && item.intersectionRatio < 1)
//target:被观察的目标元素,是一个 DOM 节点对象
item.target.src = item.target.dataset.src;
});
});
function addObserver(){
var listItems = document.querySelectorAll('.img-item');
listItems.forEach(function(item){
//实例的observe方法可以指定观察哪个DOM节点
//开始观察 observe的参数是一个 DOM 节点对象
observer.observe(item);
});
}
addObserver();
</script>