<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png" data-src="https://img.36krcdn.com/hsossms/20240612/v2_8ec7812750194dbd831babce8806c626@000000_oswg5522709oswg1792oswg1024_img_png?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center/format,webp" /> <img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png" data-src="https://img.36krcdn.com/20190808/v2_1565254363234_img_jpg"> <img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png" data-src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png"> <img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png" data-src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png"> <img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png" data-src="https://img.36krcdn.com/20190905/v2_1567642423719_img_000"> <img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png" data-src="https://img.36krcdn.com/20190905/v2_1567642425030_img_000"> <img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png" data-src="https://img.36krcdn.com/20190905/v2_1567642425101_img_000"> <img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png" data-src="https://img.36krcdn.com/20190905/v2_1567642425061_img_000"> <img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png" data-src="https://img.36krcdn.com/20190904/v2_1567591358070_img_jpg"> <img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png" data-src="https://img.36krcdn.com/20190905/v2_1567641974410_img_000"> <img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png" data-src="https://img.36krcdn.com/20190905/v2_1567641974454_img_000">在html部分中有一个重要的步骤。你会发现每一个img标签的src属性值都是一样的,我们可以复制链接到浏览器查看该图片。
img { display: block; margin-bottom: 50px; width: 400px; height: 400px; } body { background-color: gray; }通过设置img 标签样式,让小图片给真正要放的图片占位置。
const imgs = document.getElementsByTagName('img'); const num = imgs.length; let n = 0在全局一个设置scroll事件监听器,当事件触发后会调用lazyload慢加载函数。
window.addEventListener('scroll', lazyload)定义一个lazyload慢加载函数:
function lazyload() { // 堆代码 duidaima.com //可视区域的高度 let screenHeight = document.documentElement.clientHeight; //滚动条距离最顶部的距离, let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //判断图片是否存在在可视区域内 for (let i = n; i < num; i++) { if (imgs[i].offsetTop > scrollTop + screenHeight) { break; } else { //主动触发下载 imgs[i].src = imgs[i].getAttribute('data-src'); //记录已经加载过的图片数量 n = i + 1; if (n === num) { //全部加载完毕后移除滚动事件 window.removeEventListener('scroll', lazyload); } } } }
首先获取可视窗口的高度screenHeight、滚动条距离最顶部的距离scrollTop和具体图片距离最顶端的距离imgs[i].offsetTop。通过for循环遍历每个img元素。
//方法一 document.addEventListener('DOMContentLoaded', lazyload) //方法二 window.addEventListener('load', lazyload)方法一通过DOMContentLoaded事件监听器触发慢加载函数的速度比方法二通过load事件监听器触发慢加载函数的速度快。所以推荐方法一。
const imgs = document.getElementsByTagName('img'); const num = imgs.length; //用变量记录节流返回的函数 const throttleLazyLoad = throttle(lazyload, 200); //滚动事件触发懒加载 window.addEventListener('scroll', throttleLazyLoad) let n = 0 //首屏加载,DOMContentLoaded事件是DOM加载完成,不包括图片(比load事件快) document.addEventListener('DOMContentLoaded', lazyload) //首屏加载,load事件是DOM加载完成,包括图片(比DOMContentLoaded事件慢) window.addEventListener('load', lazyload) //懒加载函数 function lazyload(event) { //可视区域的高度 let screenHeight = document.documentElement.clientHeight; //滚动条距离最顶部的距离, let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //判断图片是否存在在可视区域内 for (let i = n; i < num; i++) { if (imgs[i].offsetTop > scrollTop + screenHeight) { break; } else { //主动触发下载 imgs[i].src = imgs[i].getAttribute('data-src'); //记录已经加载过的图片数量 n = i + 1; if (n === num) { //全部加载完毕后移除滚动事件 window.removeEventListener('scroll', throttleLazyLoad); } } } } //节流函数 function throttle(func, limit) { let inThrottle; return function () { const context = this; const args = arguments; if (!inThrottle) { func.apply(context, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; }
定义了一个节流函数,它接收要执行的函数 func 和时间间隔限制 limit。内部通过一个变量 inThrottle 来标记当前是否处于节流状态。当执行返回的函数时,先判断如果不在节流状态,就立即执行目标函数,并将 inThrottle 设置为 true,同时使用 setTimeout 在指定时间间隔后将 inThrottle 恢复为 false,从而实现了在规定时间间隔内只执行一次函数的节流效果,避免了频繁触发导致的性能问题。
<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>然后可以删除掉你手搓的节流函数了,使用 Lodash 库里的节流函数。
const imgs = document.getElementsByTagName('img'); const num = imgs.length; //用变量记录节流返回的函数 const throttleLazyLoad = _.throttle(lazyload, 200);//调用Lodash库里的节流函数 //滚动事件触发懒加载 window.addEventListener('scroll', throttleLazyLoad) let n = 0 //首屏加载,DOMContentLoaded事件是DOM加载完成,不包括图片(比load事件快) document.addEventListener('DOMContentLoaded', lazyload) //首屏加载,load事件是DOM加载完成,包括图片(比DOMContentLoaded事件慢) window.addEventListener('load', lazyload) //懒加载函数 function lazyload(event) { //可视区域的高度 let screenHeight = document.documentElement.clientHeight; //滚动条距离最顶部的距离, let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //判断图片是否存在在可视区域内 for (let i = n; i < num; i++) { if (imgs[i].offsetTop > scrollTop + screenHeight) { break; } else { //主动触发下载 imgs[i].src = imgs[i].getAttribute('data-src'); //记录已经加载过的图片数量 n = i + 1; if (n === num) { //全部加载完毕后移除滚动事件 window.removeEventListener('scroll', throttleLazyLoad); } } } }呈现效果