如何利用Intersection Observer API实现懒加载?

如何利用Intersection Observer API实现懒加载?
最新回答
思檀郎

2026-06-20 04:20:36

使用Intersection Observer API实现懒加载的核心是通过监听元素是否进入视口,动态加载资源以提升页面性能。 具体实现步骤如下:

1. 基础实现原理
  • 占位属性:为需要懒加载的图片设置data-src属性存储真实图片URL,初始src可为占位图或空。
  • 监听机制:通过IntersectionObserver监听元素与视口的交叉状态,当元素进入视口时触发加载。
  • 高效替代:相比传统scroll事件监听,此方法无需手动计算位置或频繁触发重绘,性能更优。
2. 关键实现步骤
  • 选择目标元素:通过document.querySelectorAll选中所有带data-src属性的图片。const images = document.querySelectorAll('img[data-src]');
  • 创建观察器实例:配置回调函数,判断元素是否进入视口。const imageObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; // 将data-src值赋给src img.removeAttribute('data-src'); // 可选:移除属性避免重复处理 observer.unobserve(img); // 停止监听已加载的图片 } });});
  • 启动观察:遍历所有目标元素,调用observe方法开始监听。images.forEach(img => imageObserver.observe(img));
3. 优化策略
  • 提前加载:通过rootMargin配置提前触发加载的阈值(如50px),使用户滚动到附近时图片已加载完成。const imageObserver = new IntersectionObserver((entries) => { /* ... */ }, { rootMargin: '50px' // 视口边缘外50px时触发});
  • 避免布局抖动:

    为图片设置固定宽高(通过CSS或width/height属性)。

    使用占位容器(如div)保持布局稳定。

  • 视觉优化:加载完成后添加淡入动画,提升用户体验。img { opacity: 0; transition: opacity 0.3s ease;}img.loaded { opacity: 1;}img.onload = () => img.classList.add('loaded');
  • 兼容性处理:引入
    Intersection Observer Polyfill
    支持旧浏览器(如IE)。
4. 完整代码示例<!DOCTYPE html><html><head> <style> img { width: 100%; height: auto; opacity: 0; transition: opacity 0.3s; } img.loaded { opacity: 1; } </style></head><body> <img data-src="image1.jpg" alt="Lazy Image 1"> <img data-src="image2.jpg" alt="Lazy Image 2"> <script> // 兼容性处理(可选) if (!('IntersectionObserver' in window)) { const script = document.createElement('script'); script.src = '
https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver';
document.head.appendChild(script); } // 懒加载实现 document.addEventListener('DOMContentLoaded', () => { const images = document.querySelectorAll('img[data-src]'); const imageObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; img.onload = () => img.classList.add('loaded'); observer.unobserve(img); } }); }, { rootMargin: '50px' }); images.forEach(img => imageObserver.observe(img)); }); </script></body></html>5. 与传统方法的对比
  • 性能优势:避免scroll事件频繁触发导致的重绘/重排,减少CPU占用。
  • 代码简洁性:无需手动计算元素位置,逻辑更清晰。
  • 扩展性:支持复杂场景(如无限滚动、动态内容加载)。

通过以上方法,可高效实现图片懒加载,显著提升页面加载速度和用户体验。