在JavaScript中实现图片延迟加载(Lazy Loading)是一种优化网页性能的有效手段,尤其在包含大量图片的长页面或图片资源较大的场景下,能够显著减少初始页面加载时间、降低带宽消耗,并提升用户体验,延迟加载的核心思想是:只有当图片即将进入用户可视区域(Viewport)时,才真正加载图片资源,而不是在页面初始渲染时就加载所有图片,以下将详细介绍几种常见的JS实现延迟加载的方法,包括其原理、代码示例及优缺点对比。

基于滚动事件和元素位置检测的传统实现
传统延迟加载主要依赖监听滚动事件(scroll),通过计算图片元素与视口的位置关系来判断是否触发加载,具体步骤如下:
- 初始状态设置:将所有延迟加载的图片
src
属性设为空或占位图,同时将真实图片URL存储在自定义属性(如data-src
)中。 - 滚动事件监听:监听页面滚动事件,当滚动发生时,遍历所有延迟加载图片,检查其是否进入视口。
- 视口判断逻辑:通过
getBoundingClientRect()
方法获取图片元素的位置信息,判断图片的顶部是否小于视口底部且图片底部大于视口顶部(即部分或全部进入视口)。 - 触发加载:若图片进入视口,则将其
src
属性值设置为data-src
中存储的URL,并移除该图片的延迟加载标记(如移除特定class或从监听列表中删除),避免重复加载。
代码示例:
document.addEventListener('DOMContentLoaded', function() { const lazyImages = document.querySelectorAll('.lazy-image'); function lazyLoad() { lazyImages.forEach(img => { const rect = img.getBoundingClientRect(); if (rect.top < window.innerHeight && rect.bottom > 0) { img.src = img.dataset.src; img.classList.remove('lazy-image'); } }); } window.addEventListener('scroll', lazyLoad); lazyLoad(); // 初始加载视口内的图片 });
HTML结构:
<img class="lazy-image" data-src="real-image.jpg" alt="Lazy loaded image">
优缺点:

- 优点:兼容性好,适用于所有浏览器,无需额外依赖。
- 缺点:频繁触发滚动事件可能导致性能问题(需结合节流优化),且对动态加载的内容支持较差。
基于Intersection Observer API的现代实现
Intersection Observer API是浏览器提供的原生API,专门用于异步监测目标元素与祖先元素或视口的交叉状态,性能更优,代码更简洁,其实现步骤如下:
- 创建Observer实例:配置
root
(根元素,默认为视口)、rootMargin
(根元素边距,用于扩展或缩小检测范围)和threshold
(阈值,触发回调的交叉比例)。 - 监听目标元素:将需要延迟加载的图片作为目标元素,通过
observer.observe()
方法添加到观察列表。 - 触发回调:当图片与视口的交叉比例达到阈值时,触发回调函数,在回调中设置图片
src
并停止观察。
代码示例:
document.addEventListener('DOMContentLoaded', function() { const lazyImages = document.querySelectorAll('.lazy-image'); const imageObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; img.classList.remove('lazy-image'); imageObserver.unobserve(img); // 停止观察已加载的图片 } }); }, { rootMargin: '0px 0px 200px 0px', // 提前200px开始加载 threshold: 0.1 }); lazyImages.forEach(img => imageObserver.observe(img)); });
优缺点:
- 优点:性能优异,无需手动管理滚动事件,支持动态元素,代码简洁。
- 缺点:兼容性有限(IE及部分旧浏览器不支持,需引入polyfill)。
结合懒加载库的实现
对于复杂项目或需要更多功能(如错误处理、占位图动画等)的场景,可使用成熟的懒加载库,如lozad.js
、lazysizes
等,这些库封装了底层逻辑,提供更丰富的配置选项。
以lozad.js为例:

- 引入库:通过CDN或npm引入。
- 初始化:选择图片元素并调用
lozad()
方法。
代码示例:
import lozad from 'lozad'; const observer = lozad('.lazy-image', { loaded: function(el) { el.classList.add('loaded'); // 添加加载完成样式 } }); observer.observe();
优缺点:
- 优点:功能完善,支持响应式图片、占位图、错误回退等,兼容性好。
- 缺点:增加外部依赖,需引入额外资源。
不同实现方式的对比
以下表格总结了三种主要实现方式的特性对比:
实现方式 | 兼容性 | 性能 | 代码复杂度 | 支持 | 额外依赖 |
---|---|---|---|---|---|
滚动事件+位置检测 | 好(所有浏览器) | 较差(需节流) | 中等 | 需手动管理 | 无 |
Intersection Observer API | 较差(需polyfill) | 优 | 低 | 自动支持 | 无(或polyfill) |
懒加载库 | 好 | 优 | 低 | 自动支持 | 有 |
注意事项
- 占位图处理:延迟加载过程中建议使用低质量占位图(LQIP)或纯色占位图,避免页面布局抖动。
- 网络不可用场景:需考虑网络异常时的错误处理,如设置
onerror
回退到默认图片。 - SEO与无障碍:确保搜索引擎爬虫和屏幕阅读器能获取图片信息,避免因延迟加载导致内容缺失。
- 适配:对于动态加载的图片(如无限滚动),需及时将其添加到观察列表。
相关问答FAQs
Q1: 延迟加载是否会影响SEO?
A1: 不会,只要确保在爬虫抓取时图片资源可被正确加载即可,现代搜索引擎(如Google)支持延迟加载,但建议在页面初始HTML中提供图片的基本信息(如alt
属性),并在爬虫可能访问的版本中预加载关键图片,可通过动态渲染或服务端渲染确保爬虫获取完整内容。
Q2: 如何处理延迟加载图片在低网速下的加载失败问题?
A2: 可通过以下方式增强容错性:
- 在
img
标签中设置onerror
事件,当加载失败时切换为默认图片或提示文字。 - 使用
loading="lazy"
属性(原生HTML延迟加载)作为兜底方案,但需注意兼容性。 - 结合库的
error
回调(如lazysizes的data-error
属性)实现统一错误处理逻辑。