一、引言
在网页开发中,图片懒加载是一种优化技术,它可以显著提高页面的加载速度和性能。当页面包含大量图片时,如果一次性加载所有图片,会导致页面初始加载时间过长,尤其是在网络较慢的情况下。图片懒加载的原理是只加载用户可见区域内的图片,当用户滚动页面时,再动态加载进入可视区域的图片。本文将介绍两种实现图片懒加载的 JavaScript 方法:ES5 监听滚动事件实现和使用新的 IntersectionObserver API 实现,并详细讨论它们的区别。
二、ES5 监听滚动事件实现图片懒加载
(一)基本原理
通过监听 window 对象的 scroll 事件,获取滚动条的位置,然后遍历页面中的图片元素,判断图片是否进入可视区域。如果图片进入可视区域,则将其 src 属性设置为真实的图片地址,从而实现图片的加载。
(二)代码实现
// 获取所有需要懒加载的图片元素
var lazyImages = document.querySelectorAll('img[data-src]');
// 定义加载图片的函数
function loadImage(image) {
if (image.getAttribute('data-src')) {
image.src = image.getAttribute('data-src');
image.removeAttribute('data-src');
}
}
// 定义检查图片是否在可视区域的函数
function isInViewport(image) {
var rect = image.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
// 监听滚动事件
window.addEventListener('scroll', function() {
lazyImages.forEach(function(image) {
if (isInViewport(image)) {
loadImage(image);
}
});
});
三、使用 IntersectionObserver API 实现图片懒加载
(一)基本原理
IntersectionObserver API 提供了一种异步观察目标元素与祖先元素或视口交叉状态变化的方法。我们可以创建一个 IntersectionObserver 实例,传入一个回调函数和配置对象,然后将需要观察的图片元素作为目标元素。当图片元素与视口的交叉状态发生变化时(如进入或离开视口),回调函数会被触发,在回调函数中可以根据交叉状态来决定是否加载图片。
(二)代码实现
// 获取所有需要懒加载的图片元素
var lazyImages = document.querySelectorAll('img[data-src]');
// 创建 IntersectionObserver 实例
var observer = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
var image = entry.target;
loadImage(image);
observer.unobserve(image);
}
});
}, {
root: null,
rootMargin: '0px',
threshold: 0.1
});
// 对每个懒加载图片元素开始观察
lazyImages.forEach(function(image) {
observer.observe(image);
});
function loadImage(image) {
if (image.getAttribute('data-src')) {
image.src = image.getAttribute('data-src');
image.removeAttribute('data-src');
}
}
四、两种实现方式的区别
(一)性能方面
- ES5 监听滚动事件:由于需要频繁监听
scroll事件,并且在事件处理函数中遍历所有图片元素进行计算和判断,即使使用了节流或防抖优化,仍然可能会消耗一定的性能,特别是在图片数量较多的情况下。而且如果页面中有其他复杂的 JavaScript 逻辑,可能会因为滚动事件处理的频繁性而影响整体性能。 - IntersectionObserver API:它是浏览器原生提供的异步观察机制,性能较好。它不需要像监听滚动事件那样频繁地进行计算和检查,只有当目标元素与视口的交叉状态发生变化时才会触发回调函数,并且浏览器会对其进行优化,以减少对主线程的阻塞。
(二)代码复杂度
- ES5 监听滚动事件:代码相对较为复杂,需要手动实现图片是否在可视区域的判断逻辑,以及处理滚动事件的监听、节流或防抖等逻辑,并且在不同浏览器中可能需要考虑兼容性问题,例如获取视口高度和宽度的方式在不同浏览器中略有不同。
- IntersectionObserver API:代码相对简洁,只需要创建
IntersectionObserver实例,传入回调函数和简单的配置对象,然后对目标元素进行观察即可。浏览器会自动处理大部分的复杂逻辑,并且兼容性也在逐渐提高(现代主流浏览器基本都支持)。
(三)兼容性
- ES5 监听滚动事件:兼容性较好,几乎所有现代浏览器以及一些较旧的浏览器都支持
scroll事件和相关的 DOM 操作。但是在处理一些低版本浏览器时,可能需要更多的兼容性代码来确保功能正常。 - IntersectionObserver API:虽然现代主流浏览器都支持,但在一些较旧的浏览器中可能不支持,需要进行兼容性处理,例如使用 polyfill 库来模拟该 API 的功能。
五、总结
图片懒加载是提高网页性能的重要技术。ES5 监听滚动事件实现图片懒加载是一种较为传统的方法,它具有较好的兼容性,但代码复杂度较高且性能相对较差,需要进行一些优化才能更好地发挥作用。而使用 IntersectionObserver API 实现图片懒加载则更加简洁高效,性能较好,但在兼容性方面需要注意对不支持该 API 的浏览器进行处理。在实际项目开发中,可以根据项目的需求和目标用户群体所使用的浏览器情况来选择合适的图片懒加载实现方式。如果需要兼容较旧的浏览器,可以先使用 ES5 监听滚动事件实现,并进行充分的优化;如果主要面向现代浏览器,那么使用 IntersectionObserver API 可以获得更好的开发体验和性能表现。