使用IntersectionObserver实现简易的图片懒加载功能

IntersectionObserver是什么?

IntersectionObserver是一个新的web API,可以自动检测某个元素是否出现在页面可视区,所以有一个通俗的名字叫 “交叉观察器”,Chrome 51+ 已经支持该特性。更详细的介绍可以看看阮一峰大神的文章:《IntersectionObserver API 使用教程》

为什么要用IntersectionObserver特性?

在此之前,我们监听页面元素是否出现在可视区,或者实现图片懒加载都是通过监听 scoll 事件,而scoll事件密集发生,容易造成性能问题。

话不多说,我们开始撸码!

HTML部分

<div class="img-list">
	<ul>
		<li><img src="http://placehold.it/300&text=Loading..." data-src="http://file06.16sucai.com/2018/0423/43a7fbe301d6d3a4c1daadd46bda8996.jpg"></li>
		<li><img src="http://placehold.it/300&text=Loading..." data-src="http://file06.16sucai.com/2018/0423/d4c853a6b08d285c809c0f22af04f4d5.jpg"></li>
		<li><img src="http://placehold.it/300&text=Loading..." data-src="http://file03.16sucai.com/2017/1100/16sucai_P591F3A175.JPG"></li>
		<li><img src="http://placehold.it/300&text=Loading..." data-src="http://file06.16sucai.com/2018/0423/18a5cf4ab618e6736806db42a7a6197b.jpg"></li>
		<li><img src="http://placehold.it/300&text=Loading..." data-src="http://file06.16sucai.com/2018/0423/7dcfc1aede6cd99b583f4149e3ad73ac.jpg"></li>
		<li><img src="http://placehold.it/300&text=Loading..." data-src="http://file06.16sucai.com/2018/0315/fa9f74d6296cd7a1ad9b79e480556c3f.jpg"></li>
		<li><img src="http://placehold.it/300&text=Loading..." data-src="http://file06.16sucai.com/2018/0315/8fc2da2c3f645e4afe992ac5c401f4f1.jpg"></li>
        </ul>
</div>

CSS部分

<style>
*{padding: 0;margin: 0;list-style: none;}
body {height: auto;width: 300px;margin: auto;}
.img-list li {width: 300px;height: auto;}
.img-list li img {width: 100%;height: auto;}
</style>

JS部分

	<script>
		window.onload = () => {
			var eles = document.querySelectorAll('.img-list li img'); // 获取所有列表元素
			
			// 监听回调
			var callback = (entries) => {
				entries.forEach(item => {
					// 出现到可视区
					if (item.intersectionRatio > 0) {
						var ele = item.target;
						var imgSrc = ele.getAttribute('data-src');
						if (imgSrc) {
							// 预加载
							var img = new Image();
							img.addEventListener('load', function() {
							    ele.src = imgSrc;
							}, false);
							ele.src = imgSrc;
							// 加载过清空路径,避免重复加载
							ele.removeAttribute('data-src');
						}
					}
				})
			}
			var observer = new IntersectionObserver(callback);

			// 列表元素加入监听
			eles.forEach(item => {
				observer.observe(item);
			})
		}
	</script>

实现起来没有什么难度,不过遇到一个问题。当不使用window.onload调用时,由于获取不到元素真实占位,会导致 callback 初次调用时会执行两次(一次是目标元素刚刚进入视口-开始可见,另一次是完全离开视口-开始不可见),这个需要注意。

完整Demo:IntersectionObserver实现懒加载

打赏支持

如果文章对你有帮助就打个赏吧~

[微信] 扫描二维码打赏

[支付宝] 扫描二维码打赏

评论

还没有任何评论,你来说两句吧

发表评论

Powered By Yuuk