var imgList = [...document.querySelectorAll("img")]; var num = imgList.length; var lazyLoad = (function () { var count = 0; return function () { var deleteIndexList = []; imgList.forEach((img, index) => { var rect = img.getBoundingClientRect(); if (rect.top < window.innerHeight) { img.src = img.dataset.src; deleteIndexList.push(index); count++; if (count === num) document.removeEventListener('scroll', lazyLoad) } }) imgList = imgList.filter((_, index) => !deleteIndexList.includes(index)); } })(); lazyLoad(); document.addEventListener('scroll', lazyLoad);
承上启下:
上边的方法是监听到scroll事件后,调用目标图片的getBoundingClientRect()方法,得到它对应于视口顶部的坐标,再判断是否在视口之内。这种方法的缺点是,由于scroll事件密集发生,计算量很大,容易造成性能问题。
目前有一个新的 IntersectionObserver API,可以自动"观察"元素是否可见,Chrome 51+ 已经支持。由于可见(visible)的本质是,目标元素与视口产生一个交叉区,所以这个 API 叫做"交叉观察器"。
function query(selector) { return Array.from(document.querySelectorAll(selector)); } var io = new IntersectionObserver(function (items) { items.forEach(function (item) { var target = item.target; if (target.getAttribute('src') == 'images/loading.gif') { target.src = target.getAttribute('data-src'); } }) }); query('img').forEach(function (item) { io.observe(item); });
参考:https://juejin.im/post/5cef46226fb9a07eaf2b7516
https://blog.csdn.net/memejie/article/details/80839089
http://www.ruanyifeng.com/blog/2016/11/intersectionobserver_api.html