news 2026/4/14 20:49:59

利用MutationObserver+IntersectionObserver实现图片懒加载

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
利用MutationObserver+IntersectionObserver实现图片懒加载

利用MutationObserver+IntersectionObserver实现图片懒加载

前言

  • 图片懒加载这并不陌生,对于前端性能优化来讲这是必经之路,
  • 我们之前做图片懒加载都是用滚动监听实现,核心逻辑是监听scroll/resize/load事件->防抖后遍历所有懒加载图片->通过getBoundingClientRect()计算图片位置,判断是否进入视口->加载图片
  • 伪代码
window.addEventListener('scorll',debounce(()=>{document.querySelectorAll('img[data-lazy-src]').forEach(img=>{constrect=img.getBoundingClientRect()if(rect.top<window.innerHeight+200&&rect.bottom>0){img.src=img.dataset.lazySrc}})}))
  • 这么做可以实现么,可以,但是有没有缺点呢,有
    1. 高消耗,scroll事件高频触发,及时使用了防抖,仍有频繁执行;且每次触发需要遍历所有懒加载图片,调用getBoundingClientRect;无法自动停止监听,及时图片已加载,仍会参与遍历
    1. 动态图片无法覆盖,无法捕获异步新增的图片,需要手动调用检查函数
    1. 开发成高,需要手动实现防抖、视口判断、边界条件(如提前加载、窗口缩放);需要手动处理动态图片,容易遗漏动态图片;需要手动避免重复加载
    1. 精度低,视口判断依赖getBoundingClientRect(),受CSS变形,滚动条等影响,容易计算错误;
    1. 稳定性差,因为有防抖延迟,可能导致图片延迟加载,高频滚动是js阻塞,可能导致页面卡顿
  • 等等,会有一系列的问题,而这些问题的根源在于判断图片是否进入视口时需要用scroll去监听
  • 那有没有不需要通过scroll去监听就能判断图片是否进入视口的方法呢,真好,还真有
  • 这个玩意叫InterSectionObserver,翻译为交叉观察器

IntersectionObserver

  • 这是个啥玩意呢,他的作用就是目标元素与视口产生一个交叉区,看看这个交叉区的比率是多少,如果是0,则不可见,100则完全可见(0-100)则部分可见
  • 怎么用呢,直接上代码
constobserver=newInterSectionObserver((entries,observer)=>{entries.forEach(entry=>{if(entry.inIntersecting){console.log('元素进入视口')}})})observer.oberve(document.qerySelector('target'))
  • 构造函数new IntersectionObserver(callback,options),callback是回调函数
  • options是配置项
  • 主要有三个配置项,root,相对哪个容器进行检测
  • rootMargin,扩展和收缩检测区域,可以理解为预支量,做预加载使用
  • threshold,触发回调的交叉比例
参数类型默认值说明
rootElement nullnull(viewport)相对哪个容器检测(如滚动容器)
rootMarginstring“0px”扩展/收缩检测区域(类似 margin,支持百分比)
hresholdnumber number[]0触发回调的交叉比例(0~1 或 [0, 0.5, 1])
  • callback中(entry)的信息如下
time:45325//触发时间rootBounds:DOMRectReadonly//root的边界boundingClientRect:DOMRect//目标元素边界intersectionRect:DOMREct//交叉区域intersectionRatio:05//交叉比例isIntersecting:true//是否相交intersectionRatio>thresholdtarget:element//被观察者对象
  • 讲完了IntersectionObserver,上篇文章我们还讲了MutationObserver,现在用这两个设计一个图片懒加载的实现

图片懒加载

设计思路

  • 我们理一下,我们要干这么几件事

    1. 创建视口监听器和动态监听器
    1. 处理页面上初始IMG
    1. 处理动态新增的IMG
  • 上个详细的流程图

  • 为了更好的管理和组织,我们可以设计一个类lazyImagesLoder

  • 里面有上述的5个基本方法和4个基本属性

  • 基本属性包括配置属性config,视口实例intersectionObserver,DOM监听实例mutationObserver以及防止重复监听的容器observedImgs

  • 接下来就是代码组织了

  • 上代码

<!-- 懒加载图片:用><imgdata-lazy-src="1.jpg"alt="示例图片1"/><imgdata-lazy-src="2.jpg"alt="示例图片2"/><!-- 动态生成的图片(也会被监听) --><buttononclick="addDynamicImg()">新增图片</button
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/13 4:57:55

基于JAVA的医院住院管理系统

基于JAVA的医院住院管理系统设计与实现 第一章 绪论 传统医院住院管理多依赖人工记录与纸质单据流转&#xff0c;存在信息查询繁琐、数据统计滞后、流程衔接不畅等问题。例如&#xff0c;患者入院登记需手动填写多份表格&#xff0c;病房床位状态更新不及时易导致分配冲突&…

作者头像 李华
网站建设 2026/4/15 10:34:09

Miniconda-Python3.9环境下实现PyTorch模型GitOps部署

Miniconda-Python3.9环境下实现PyTorch模型GitOps部署 在AI研发日益工程化的今天&#xff0c;一个常见的痛点是&#xff1a;数据科学家在本地训练好的模型&#xff0c;一旦交给运维团队部署&#xff0c;就频频报错——“ImportError: cannot import name ‘XXX’”&#xff0c;…

作者头像 李华
网站建设 2026/4/14 22:11:19

通过Miniconda-Python3.9快速启动Jupyter Notebook进行AI开发

通过Miniconda-Python3.9快速启动Jupyter Notebook进行AI开发 在人工智能项目日益复杂的今天&#xff0c;一个常见的痛点浮出水面&#xff1a;为什么同样的代码&#xff0c;在同事的机器上跑得好好的&#xff0c;到了你的环境却报错不断&#xff1f;问题往往不在于代码本身&…

作者头像 李华
网站建设 2026/4/15 10:35:12

MSVCP70.DLL文件损坏丢失找不到 打不开软件 下载方法

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/4/14 16:11:29

0基础在Windows本地搭建“DeepSeek”私人知识库

在这个AI爆发的时代&#xff0c;你是否想过把电脑里的几百份PDF、Word文档变成一个可以随时提问的“超级大脑”&#xff1f;而且完全免费、不用联网、数据不出本地&#xff01; 今天手把手教大家利用 Ollama DeepSeek Python 搭建一个本地 RAG&#xff08;检索增强生成&#…

作者头像 李华