菜鸟科技网

JS如何实现图片延迟加载?

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

JS如何实现图片延迟加载?-图1
(图片来源网络,侵删)

基于滚动事件和元素位置检测的传统实现

传统延迟加载主要依赖监听滚动事件(scroll),通过计算图片元素与视口的位置关系来判断是否触发加载,具体步骤如下:

  1. 初始状态设置:将所有延迟加载的图片src属性设为空或占位图,同时将真实图片URL存储在自定义属性(如data-src)中。
  2. 滚动事件监听:监听页面滚动事件,当滚动发生时,遍历所有延迟加载图片,检查其是否进入视口。
  3. 视口判断逻辑:通过getBoundingClientRect()方法获取图片元素的位置信息,判断图片的顶部是否小于视口底部且图片底部大于视口顶部(即部分或全部进入视口)。
  4. 触发加载:若图片进入视口,则将其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">

优缺点

JS如何实现图片延迟加载?-图2
(图片来源网络,侵删)
  • 优点:兼容性好,适用于所有浏览器,无需额外依赖。
  • 缺点:频繁触发滚动事件可能导致性能问题(需结合节流优化),且对动态加载的内容支持较差。

基于Intersection Observer API的现代实现

Intersection Observer API是浏览器提供的原生API,专门用于异步监测目标元素与祖先元素或视口的交叉状态,性能更优,代码更简洁,其实现步骤如下:

  1. 创建Observer实例:配置root(根元素,默认为视口)、rootMargin(根元素边距,用于扩展或缩小检测范围)和threshold(阈值,触发回调的交叉比例)。
  2. 监听目标元素:将需要延迟加载的图片作为目标元素,通过observer.observe()方法添加到观察列表。
  3. 触发回调:当图片与视口的交叉比例达到阈值时,触发回调函数,在回调中设置图片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.jslazysizes等,这些库封装了底层逻辑,提供更丰富的配置选项。
以lozad.js为例

JS如何实现图片延迟加载?-图3
(图片来源网络,侵删)
  1. 引入库:通过CDN或npm引入。
  2. 初始化:选择图片元素并调用lozad()方法。

代码示例

import lozad from 'lozad';
const observer = lozad('.lazy-image', {
  loaded: function(el) {
    el.classList.add('loaded'); // 添加加载完成样式
  }
});
observer.observe();

优缺点

  • 优点:功能完善,支持响应式图片、占位图、错误回退等,兼容性好。
  • 缺点:增加外部依赖,需引入额外资源。

不同实现方式的对比

以下表格总结了三种主要实现方式的特性对比:

实现方式 兼容性 性能 代码复杂度 支持 额外依赖
滚动事件+位置检测 好(所有浏览器) 较差(需节流) 中等 需手动管理
Intersection Observer API 较差(需polyfill) 自动支持 无(或polyfill)
懒加载库 自动支持

注意事项

  1. 占位图处理:延迟加载过程中建议使用低质量占位图(LQIP)或纯色占位图,避免页面布局抖动。
  2. 网络不可用场景:需考虑网络异常时的错误处理,如设置onerror回退到默认图片。
  3. SEO与无障碍:确保搜索引擎爬虫和屏幕阅读器能获取图片信息,避免因延迟加载导致内容缺失。
  4. 适配:对于动态加载的图片(如无限滚动),需及时将其添加到观察列表。

相关问答FAQs

Q1: 延迟加载是否会影响SEO?
A1: 不会,只要确保在爬虫抓取时图片资源可被正确加载即可,现代搜索引擎(如Google)支持延迟加载,但建议在页面初始HTML中提供图片的基本信息(如alt属性),并在爬虫可能访问的版本中预加载关键图片,可通过动态渲染或服务端渲染确保爬虫获取完整内容。

Q2: 如何处理延迟加载图片在低网速下的加载失败问题?
A2: 可通过以下方式增强容错性:

  • img标签中设置onerror事件,当加载失败时切换为默认图片或提示文字。
  • 使用loading="lazy"属性(原生HTML延迟加载)作为兜底方案,但需注意兼容性。
  • 结合库的error回调(如lazysizes的data-error属性)实现统一错误处理逻辑。
分享:
扫描分享到社交APP
上一篇
下一篇