先上代码
HTML
<img class="lazy-img" data-src="demo.jpg">
JavaScript
var lazyImgList = [].slice.call(document.querySelectorAll('.lazy-img'), 0);
function lazyload() {
var viewHeight = window.innerHeight || document.documentElement.clientHeight; //可见区域高度
lazyImgList = lazyImgList.filter(function (imgNode) {
var imgRectTop = imgNode.getBoundingClientRect().top;
if (imgRectTop <= viewHeight) {
imgNode.src = imgNode.getAttribute("data-src");
return false;
}
return true;
});
if (lazyImgList.length === 0) window.removeEventListener('scroll', lazyload);
}
lazyload();
window.addEventListener('scroll', lazyload);
原理
- imgEl.getBoundingClientRect().top:是一个随滚动变化的值,是元素顶部距离视口顶部的距离;
- window.innerHeight:浏览器窗口的视口(viewport)高度。
如图,当 imgEl.getBoundingClientRect().top <= window.innerHeight 时,元素进入视口,此时赋值图片的 src = data-src ,开始加载。
思考🤔
- 使用 lazyImgList = lazyImgList.filter(···) 过滤掉已经加载过的图片。
- imgRectTop - threshold <= viewHeight :可以添加一个阀值来控制图片出现在视口前加载,优化体验。
- 如果需要对背景图进行懒加载,同样可以比较容器的DOMRect的top值与window.innerHeight的差值,来添加类名实现。(或通过js添加background-image)
- <img src=···> 和背景图 代码解析到的时候都会发送资源请求,与display:none无关(可利用此特效实现预加载)。
- window.innerHeight 不兼容 IE<9 的版本,使用 viewHeight = window.innerHeight || document.documentElement.clientHeight;
- 根据需要对scroll事件进行节流。