如何用JavaScript实现图片懒加载_交叉观察器怎么用
发布时间 - 2026-01-01 00:00:00 点击率:次IntersectionObserver 是浏览器原生异步回调机制,用于监听元素进入/离开视口,性能优于 scroll + getBoundingClientRect();它不触发强制同步布局,支持 root、threshold、rootMargin 配置,需处理加载失败、重复绑定、内存泄漏等问题,并在不支持时降级为节流 scroll + requestIdleCallback。
IntersectionObserver 是什么,为什么不用 getBoundingClientRect
它不是轮询检测,而是浏览器原生的异步回调机制,性能远好于 scroll + getBoundingClientRect()。尤其在长列表或滚动频繁的页面里,后者容易触发强制同步布局(Layout Thrashing),造成卡顿。
关键点:它只在元素进入/离开视口时才通知,且不阻塞主线程;而 getBoundingClientRect() 每次调用都可能触发重排。
基本用法:监听图片是否进入视口并加载
核心是创建一个 IntersectionObserver 实例,传入回调函数和配置项,再用 observe() 绑定目标 元素。
-
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 不会二次触发。
- 务必监听
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 或工具函数,把判断、绑定、错误处理、清理全包进去。
# css
# javascript
# java
# html
# go
# 浏览器
# 回调函数
# 工具
# 懒加载
# ssl
# safari
# win
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
C++用Dijkstra(迪杰斯特拉)算法求最短路径
Python面向对象测试方法_mock解析【教程】
百度输入法全感官ai怎么关 百度输入法全感官皮肤关闭
详解jQuery停止动画——stop()方法的使用
Laravel如何实现API版本控制_Laravel版本化API设计方案
如何快速搭建高效WAP手机网站?
Laravel怎么配置自定义表前缀_Laravel数据库迁移与Eloquent表名映射【步骤】
Laravel怎么创建控制器Controller_Laravel路由绑定与控制器逻辑编写【指南】
如何登录建站主机?访问步骤全解析
网站优化排名时,需要考虑哪些问题呢?
php在windows下怎么调试_phpwindows环境调试操作说明【操作】
如何注册花生壳免费域名并搭建个人网站?
如何快速选择适合个人网站的云服务器配置?
如何实现建站之星域名转发设置?
Laravel Eloquent:优雅地将关联模型字段扁平化到主模型中
Laravel怎么调用外部API_Laravel Http Client客户端使用
Android仿QQ列表左滑删除操作
如何快速查询网址的建站时间与历史轨迹?
phpredis提高消息队列的实时性方法(推荐)
Laravel如何发送系统通知?(Notification渠道示例)
如何快速搭建二级域名独立网站?
如何在自有机房高效搭建专业网站?
Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程
Python文件流缓冲机制_IO性能解析【教程】
车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?
高防网站服务器:DDoS防御与BGP线路的AI智能防护方案
制作旅游网站html,怎样注册旅游网站?
如何快速搭建FTP站点实现文件共享?
如何破解联通资金短缺导致的基站建设难题?
laravel怎么配置Redis作为缓存驱动_laravel Redis缓存配置教程
PHP的CURL方法curl_setopt()函数案例介绍(抓取网页,POST数据)
Laravel Blade模板引擎语法_Laravel Blade布局继承用法
手机软键盘弹出时影响布局的解决方法
如何快速配置高效服务器建站软件?
今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
Linux系统命令中screen命令详解
如何在万网ECS上快速搭建专属网站?
Laravel如何操作JSON类型的数据库字段?(Eloquent示例)
实现点击下箭头变上箭头来回切换的两种方法【推荐】
如何正确选择百度移动适配建站域名?
Laravel Sail是什么_基于Docker的Laravel本地开发环境Sail入门
Firefox Developer Edition开发者版本入口
动图在线制作网站有哪些,滑动动图图集怎么做?
网站制作软件免费下载安装,有哪些免费下载的软件网站?
深圳防火门网站制作公司,深圳中天明防火门怎么编码?
HTML透明颜色代码在Angular里怎么设置_Angular透明颜色使用指南【详解】
如何在万网利用已有域名快速建站?
Laravel如何实现API版本控制_Laravel API版本化路由设计策略
Android使用GridView实现日历的简单功能


理加载失败、重复绑定、内存泄漏等问题,并在不支持时降级为节流 scroll + requestIdleCallback。