本博客 hjy-xh,转载请申明出处
懒加载概念
懒加载也叫延迟加载,指的是在长网页中延迟加载图像,是一种很好优化网页性能的方式。
用户滚动到它们之前不加载,也就是在可视区域之外的图像不会加载。
使用场景和优势
在一些电商类的项目中,往往存在大量的图片,比如广告图、商品图等等。图片的数量和体积会影响页面加载速度,而进行图片懒加载优化可以大幅提升用户体验
减少无效资源的加载
防止并发加载的资源过多会阻塞JS的加载
可以看出来,懒加载的核心目的就是提升用户的体验
实现
思路一
将页面上的图片的 src 属性设置为项目中引入一个默认的图片路径,而图片的真实路径则设置在自定义数据属性中,比如说data-original
, 同时监听scroll事件,在scroll事件的回调中,判断需要进行懒加载的图片是否进入可视区域,如果图片在可视区内将图片的 src
属性设置为data-original
的值
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| <html lang="en">
<head> <meta charset="UTF-8"> <title>Lazyload</title> <style> .image-item { display: block; margin-bottom: 50px; height: 200px; } </style> </head>
<body> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/1.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/2.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/3.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/4.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/5.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/6.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/7.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/8.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/9.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/10.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/11.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/12.png" /> <script> const viewHeight = document.body.clientHeight;
function lazyload() { const imgs = document.querySelectorAll("img[data-src][lazyload]"); Array.prototype.forEach.call(imgs, function (item, index) { let rect = null; if (item.dataset.original === "") return; rect = item.getBoundingClientRect(); if (rect.bottom >= 0 && rect.top < viewHeight) { const img = new Image(); img.src = item.dataset.original; img.onload = function () { item.src = img.src; }; item.removeAttribute("data-src"); item.removeAttribute("lazyload"); } }); }
function throttle(fn, delay) { let tiemr = null; return function (args) { let that = this; let _args = args; if (!tiemr) { timer = setTimeout(function () { fn.call(that, _args); timer = null; }, delay); }
} }
lazyload(); document.addEventListener("scroll", throttle(lazyload, 200)); </script> </body>
</html>
|
思路二
思路一需要去监听 scroll
事件,虽然通过函数节流的方式来阻止高频率的执行函数,但是还是需要去计算高度等属性,而 IntersectionObserver
接口提供了一种异步观察目标元素与其祖先元素或顶级文档视口(viewport)交叉状态(可见)的方法。
相关API介绍
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| <html lang="en">
<head> <meta charset="UTF-8"> <title>Lazyload</title> <style> .image-item { display: block; margin-bottom: 50px; height: 200px; } </style> </head>
<body> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/1.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/2.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/3.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/4.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/5.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/6.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/7.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/8.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/9.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/10.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/11.png" /> <img src="./images/loading.png" class="image-item" lazyload="true" data-src="images/12.png" /> <script> const imgs = document.querySelectorAll('img[data-src]') const config = { rootMargin: '0px', threshold: 0, } let observer = new IntersectionObserver((entries, self) => { entries.forEach((entry) => { if (entry.isIntersecting) { let img = entry.target let src = img.dataset.src if (src) { img.src = src img.removeAttribute('data-src') img.removeAttribute("lazyload"); } self.unobserve(entry.target) } }) }, config)
imgs.forEach((image) => { observer.observe(image) })
</script> </body>
</html>
|