如何用JavaScript实现图片懒加载_交叉观察器怎么用

16次阅读

IntersectionObserver 是浏览器原生异步回调机制,用于监听元素进入/离开视口,性能优于 scroll + getBoundingClientRect();它不触发强制同步布局,支持 root、threshold、rootmargin 配置,需处理加载失败、重复绑定、内存泄漏等问题,并在不支持时降级为节流 scroll + requestIdleCallback。

如何用JavaScript实现图片懒加载_交叉观察器怎么用

IntersectionObserver 是什么,为什么不用 getBoundingClientRect

它不是轮询检测,而是浏览器原生的异步回调机制,性能远好于 scroll + getBoundingClientRect()。尤其在长列表或滚动频繁的页面里,后者容易触发强制同步布局(Layout Thrashing),造成卡顿。

关键点:它只在元素进入/离开视口时才通知,且不阻塞线程;而 getBoundingClientRect() 每次调用都可能触发重排。

基本用法:监听图片是否进入视口并加载

核心是创建一个 IntersectionObserver 实例,传入回调函数和配置项,再用 observe() 绑定目标 如何用JavaScript实现图片懒加载_交叉观察器怎么用 元素。

  • root:默认为浏览器视口;设为某个容器元素时,就以该容器为“视口”边界
  • threshold:0~1 的数组,表示目标元素多少比例进入 root 时触发回调(如 [0, 0.25, 0.5, 0.75, 1]
  • rootMargin:类似 css margin,可提前触发(如 "100px" 表示元素距离视口还有 100px 就开始加载)
const imgObserver = new IntersectionObserver(   (entries) => {     entries.forEach(entry => {       if (entry.isIntersecting) {         const img = entry.target;         img.src = img.dataset.src;         img.classList.remove('lazy');         imgObserver.unobserve(img); // 加载完就停止监听       }     });   },   {     rootMargin: '100px', // 提前加载,防滚动过快出现空白     threshold: 0.1   } );  document.querySelectorAll('img.lazy').forEach(img => {   imgobserver.observe(img); });

常见坑:图片加载失败后没 fallback、重复绑定、未解绑

懒加载不是加个 src 就完事——网络异常、路径错误、CORS 都会让 img 显示为空白,且 IntersectionObserver 不会二次触发。

立即学习Java免费学习笔记(深入)”;

  • 务必监听 img.onerror,降级显示占位图或提示文字
  • 避免对同一张图多次 observe()(比如组件重复渲染时没清理旧 observer)
  • unobserve() 要及时调用;否则即使图片已加载,observer 仍持有引用,影响内存回收
  • 服务端返回的 html 若含 src,要确保它为空或为占位图,否则浏览器会提前发起请求,失去懒加载意义

兼容性与降级方案:safari 12.1+ 和 IE 完全不支持

如果必须支持 Safari 12 或更早版本,不能直接用 IntersectionObserver。可用 scroll + requestIdleCallback 组合做轻量降级,但要注意节流。

简单判断:

if ('IntersectionObserver' in window) {   // 使用 IntersectionObserver } else {   // 降级:监听 scroll,用 getBoundingClientRect + throttle   // 注意:避免在回调中直接操作 DOM,优先用 requestIdleCallback 延后执行 }

真正麻烦的不是写降级逻辑,而是混合使用时容易漏掉 unobserve 或重复绑定;建议项目里统一抽象成一个 useLazyImage Hook 或工具函数,把判断、绑定、错误处理、清理全包进去。

text=ZqhQzanResources