【JS】详解浏览器的5 种Observer: Mutation、Intersection、Performance、Resize、Reporting

news2024/11/15 12:20:20

文章目录

    • 1、IntersectionObserver 交叉观察器
      • 用法
      • 使用场景
    • 2、MutationObserver 变动观察器
      • 用法
      • 使用场景
    • 3、ResizeObserver 尺寸变化观察器
      • 用法
      • 使用场景
    • 4、PerformanceObserver 性能观察器
      • 用法
      • 使用场景
    • 5、ReportingObserver
      • 用法
      • 使用场景
    • 总结

网页开发中我们经常要处理用户交互,我们会用 addEventListener 添加事件监听器来监听各种用户操作,比如 click、mousedown、mousemove、input 等,这些都是由用户直接触发的事件。

那么对于一些不是由用户直接触发的事件呢? 比如元素从不可见到可见、元素大小的改变、元素的属性和子节点的修改等,这类事件如何监听呢?

浏览器提供了 5 种 Observer 来监听这些变动IntersectionObserverMutationObserverResizeObserverPerformanceObserverReportingObserver

1、IntersectionObserver 交叉观察器

IntersectionObserver是一个 Web API,它可以异步地监测一个元素与其祖先或顶级文档视口之间的交叉状态。它会告诉我们目标元素是否进入或离开了视口,或者与其他元素重叠。
在这里插入图片描述

用法

const io = new IntersectionObserver(callback, option);
IntersectionObserver 是浏览器原生提供的构造函数,接受两个参数:

  • callback:可见性发现变化时的回调函数。callback一般会触发两次。一次是目标元素刚刚进入视口,另一次是完全离开视口。
  • option:配置对象(可选)
    1. threshold: 决定了什么时候触发回调函数。它是一个数组,每个成员都是一个门槛值,默认为[0],即交叉比例(intersectionRatio)达到0时触发回调函数。用户可以自定义这个数组。比如,[0, 0.25, 0.5, 0.75, 1]就表示当目标元素 0%、25%、50%、75%、100% 可见时,会触发回调函数。
    2. root: 用于观察的根元素,默认是浏览器的视口,也可以指定具体元素,指定元素的时候用于观察的元素必须是指定元素的子元素
    3. rootMargin: 用来扩大或者缩小视窗的的大小,使用css的定义方法,10px 10px 30px 20px表示top、right、bottom 和 left的值。可以使用像素或百分比来调整边界区域。

构造函数的返回值是一个观察器实例。实例一共有4个方法:

  1. observe: 开始监听特定元素
  2. unobserve: 停止监听特定元素
  3. disconnect: 关闭监听工作
  4. takeRecords: 返回所有观察目标的对象数组
// 获取元素
const target = document.getElementById("dom");

const options = {
    root: null, // 视口的根元素,默认为整个文档视口
    rootMargin: '0px',
    threshold: 0.5 // 目标元素可见度的阈值,默认为 0(完全不可见)到 1(完全可见)
};
// 实例化交叉观察器
const io = new IntersectionObserver(callback, option);

// 开始观察:该方法需要接收一个target参数,值是Element类型,用来指定被监听的目标元素
io.observe(target);

// 停止观察:该方法需要接收一个target参数,值是Element类型,用来指定停止监听的目标元素
io.unobserve(target);

// 关闭观察器:该方法不需要接收参数,用来关闭观察器
io.disconnect();

// 获取被观察元素:该方法不需要接收参数,返回所有被观察的对象,返回值是一个数组
const observerList = io.takeRecords();

使用场景

实现滚动动画、懒加载、虚拟列表、加载更多、元素吸顶、吸底

2、MutationObserver 变动观察器

MutationObserver是一个 Web API,用于异步监听DOM对象的变更(包括子节点),当节点属性发生变化,或执行增删改操作时执行对应的callback。MutationObserver为我们提供了一种十分方便的监听DOM变化的方式。

注:在Mutation标准化之前,开发者对DOM变化的非官方监听方式是使用定时器(轮询)机制,通过setTimeout或者setInterval来进行宏任务创建,观察节点的变化;

用法

const mo = new MutationObserver(target, option);
MutationObserver 是浏览器原生提供的构造函数,接受两个参数:

  • target: 目标元素
  • option:配置对象
    1. childList:默认为false,设置为true,可观察目标子节点的变化;比如添加或删除目标子节点,不包括修改子节点以及子节点后代的变化
    2. subtree:默认是false,设置为true后可观察后代节点
    3. attributes:默认为false,设置为true,可观察目标属性的改变
    4. attributeFilter:特性名称数组,只观察选定的特性
    5. characterData:是否观察文本内容
    6. attributeOldValue:是否将特性的旧值和新值都传递给回调,如果设置为true或省略,则相当于设置为true,表示需要记录改变前的目标属性值,设置了attributeOldValue可以不用设置attribute
    7. characterDataOldValue:是否将 node.data 的旧值和新值都传递给回调,如果设置为true或省略,则相当于设置为true,表示需要记录改变之前的目标数据,设置了characterDataOldValue可以不用设置characterData
// 目标元素
const targetElement = document.querySelector('#target');

// 创建一个MutationObserver实例
const mo= new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    if (mutation.type === 'childList') {
      mutation.addedNodes.forEach((addedNode) => {
        console.log(`添加了子元素:${addedNode.nodeName}`);
        // 执行相应的处理逻辑
      });

      mutation.removedNodes.forEach((removedNode) => {
        console.log(`移除了子元素:${removedNode.nodeName}`);
        // 执行相应的处理逻辑
      });
    }
  });
});

// 配置观察器
const config = {
  childList: true, // 观察直接子节点
  subtree: true, // 及其更低的后代节点
};

// 启动观察器
mo.observe(targetElement, config);

使用场景

监测元素的添加或移除、动态内容加载、表单验证、响应式布局、自定义组件开发

3、ResizeObserver 尺寸变化观察器

ResizeObserver 用于监听元素的尺寸变化。 在前端开发中,元素尺寸的变化可能会受到许多因素的影响,例如窗口大小调整、设备方向变化、内部内容变化等。 提供了一种高效的方法来响应这些变化,而不需要频繁使用事件监听器或轮询技术。(窗口我们可以用 addEventListener 监听 resize 事件)

用法

const ro = new ResizeObserver(callback);

ResizeObserver是浏览器原生提供的构造函数,接受一个参数:

  • callback:监听元素尺寸发生变化时,会触发回调函数。回调函数接收一个变化对象数组参数,每个对象中包含了尺寸变化的相关信息。

构造函数的返回值是一个尺寸变化观察器实例。实例一共有3个方法:

  1. observe: 开始监听特定元素
  2. unobserve: 停止监听特定元素
  3. disconnect: 关闭监听工作
// 获取目标元素
const ele = document.getElementsByClassName('list-item');
const ro = new ResizeObserver(callback);

function callback(entries){
    for(const entry of entries){
        const rect = entry.contentRect;
        console.log('当前大小', rect);
    }
}

// 开始监听
ro.observe(ele);
// 结束监听
ro.unobserve(ele);
// 取消监听所有目标元素
ro.disconnect();

使用场景

  1. 响应式布局: 随着元素尺寸的变化,动态调整布局或样式。
  2. 动态容器: 监听内容动态加载的容器的尺寸,以便进行布局调整。
  3. Canvas 渲染: 根据容器的尺寸变化,动态调整 canvas 的渲染尺寸或内容。
  4. SVG 调整: 动态调整 SVG 图形的尺寸或形状。

4、PerformanceObserver 性能观察器

PerformanceObserver是一个 Web API,它可以异步地监听浏览器的performance事件,方便在performance事件触发时作统一处理。用于记录一些时间点、某个时间段、资源加载的耗时等,以便收集和分析页面性能数据。

用法

// 1.创建Performance Observer实例
const po = new PerformanceObserver(callback);
回调函数会在性能指标发生变化时被触发,它接受一个参数:entries,它是一个性能条目对象的数组,每个对象描述了一个性能条目。

// 2.指定要观察的性能条目类型
po.observe({ entryTypes: ['resource', 'paint'] });
性能条目类型是一个配置对象,包括以下属性:

entryTypes:一个数组,包含要观察的性能条目类型
可以填的值包括:
frame: 指的是整个页面,包括页面的导航性能和整体加载时间。它可以监测与整个页面的性能相关的数据。 
navigation: 与页面导航和加载时间相关,提供有关导航事件(如页面加载、重定向等)的性能数据。
resource: 与页面中加载的各种资源相关,如图像、脚本、样式表等。它可以监测单个资源的加载性能,包括资源的开始和结束时间,以及其他相关信息。
mark: 与性能标记(mark)相关,性能标记是在代码中设置的时间戳,通常用于记录特定事件的时间,以便后续性能分析。这提供了在页面加载期间创建性能标记的方式。
measure: 与性能测量(measure)相关,性能测量用于测量两个性能标记之间的时间间隔,以获取更详细的性能数据。这提供了测量和分析特定事件之间的时间差的方式。
paint: 与页面绘制性能相关,可以是 "first-paint"(首次绘制)或 "first-contentful-paint"(首次内容绘制)之一。这些指标表示页面呈现的关键时间点,可以帮助我们评估用户视觉上的加载体验。

使用场景

记录某个时间点、某个时间段、资源加载的耗时并上报数据,做性能分析。

更多详细内容:https://juejin.cn/post/7294532494343159843

5、ReportingObserver

ReportingObserver用于监听浏览器报告的事件,例如废弃API,过时特性,网络错误。做监控SDK的同学应该经常能用到,日常业务代码用的比较少。
在这里插入图片描述

浏览器还会在一些情况下对网页行为做一些干预(intervention),比如会把占用 cpu 太多的广告的 iframe 删掉。
会在网络比较慢的时候把图片替换为占位图片,点击才会加载。
这些干预都是浏览器做的,会在控制台打印一个报告,但是这些干预或者过时的 api 并不是报错,所以不能用错误监听的方式来拿到,但这些情况对网页来说可能也是很重要的。

用法

const reportingObserver = new ReportingObserver((reports, observer) => {
    for (const report of reports) {
        console.log(report.body);//上报
    }
}, {types: ['intervention', 'deprecation']});

reportingObserver.observe();

使用场景

ReportingObserver 可以监听过时的 api、浏览器干预等报告等的打印,在回调里上报,这些是错误监听无法监听到但对了解网页运行情况很有用的数据。

总结

监听用户的交互行为,我们会用 addEventListener 来监听 click、mousedown、keydown、input 等事件,但对于元素的变化、performance 的记录、浏览器干预行为这些不是用户交互的事件就要用 XxxObserver 的 api 了。
浏览器提供了这 5 种 Observer:

  1. IntersectionObserver:监听元素可见性变化,常用来做元素显示的数据采集、图片的懒加载
  2. MutationObserver:监听元素属性和子节点变化,比如可以用来做去不掉的水印
  3. ResizeObserver:监听元素大小变化

还有两个与元素无关的:

  1. PerformanceObserver:监听 performance 记录的行为,来上报数据
  2. ReportingObserver:监听过时的 api、浏览器的一些干预行为的报告,可以让我们更全面的了解网页 app 的运行情况

这些 api 相比 addEventListener 添加的交互事件来说用的比较少,但是在特定场景下都是很有用的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2034507.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第三方jar自带logback导致本地日志文件不生成

1.问题及解决 这是依赖的jar包,自己有logback,只打印到控制台,导致我们项目里配置的error级别日志不会生成到日志文件中去。ai给的答案是自己控制加载顺序,但很麻烦,--logging.config也不行,最好下了个7z压…

Grafana 可视化监控和告警

前言 在现代分布式系统和云原生环境中,为了确保复杂的分布式系统和服务的高可用性、可靠性和性能,通常采用实时可视化监控和分析,实现故障快速响应、资源优化和安全保障,从而提升用户满意度和运营效率。 在目前主流的解决方案中…

vue 获取当前页面路由

vue2 : import { getCurrentInstance } from ‘vue’; //获取当前页路由 data() { return { currentRouter: ‘’,//默认路由 } } const { proxy } getCurrentInstance(); this.currentRouter proxy.$router.currentRoute.meta.title vue3 : import …

智能语音电话机器人的优势有哪些?

现在每个企业的客服成本都是非常高的,但是工作效率还不高,有的还存在简单粗暴的情况,因此如果使用语音机器人的话,就将会发生重大的转变了,不仅会提高效率,还会降低很多的人力成本,,…

【浏览器】f12控制台,如何选中click、hover才出现的元素(断点调试)

使用断点调试 以切换语言的弹窗为例 当鼠标点击select框时才显现选项,没有办法直接选中元素进行样式的调试 1. 按f12打开控制台,点击sources,按 ctrlo 查找你要开发的文件 2. 给元素添加断点(如果操作的时候没有停,就…

丰田的接单式生产、零库存、快速换模之间关系如何?

前面讲了,丰田采用接单式生产,这让它的库存一直保持在较低水平,但这一切是怎么实现的?接单式生产、零库存和快速换模之间又有怎样的关系?今天就来简单聊下。 接单式生产 这可谓是丰田典型的快速响应。当4S门店销售人员…

[openSSL]TLS 1.3握手分析

文章目录 前言一、ECDHE密钥交换二、TLS单向身份认证三、TLS双向身份认证 前言 关于TLS握手网上资料很多,但是有一些写的很不清楚,导致学习时对概念和流程出现混淆,以下是我觉得写得比较清晰和准确的供学习参考。 浅析 TLS(ECDHE…

【C++ 面试 - 基础题】每日 3 题(十三)

✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏&…

【原创】java+swing+mysql简单图书信息管理系统设计与实现

个人主页:程序员杨工 个人简介:从事软件开发多年,前后端均有涉猎,具有丰富的开发经验 博客内容:全栈开发,分享Java、Python、Php、小程序、前后端、数据库经验和实战 开发背景: 编程小白们刚入…

Lua语言基础学习:安装Lua和Lua库管理工具

Lua语言简介 Lua是一种轻量、高效、可嵌入的脚本语言,由巴西里约热内卢天主教大学的研究小组于1993年开发,Lua的解释器非常小巧,编译后的体积很小(如完整解释器不过200KB),这使得它非常适合嵌入到其他应用程…

基于Linux系统中的 【环境变量】 详细讲解

目录 一、环境变量的基本概念 二、环境变量的认识 1、常见的环境变量 2、查看环境变量的方法 3、环境变量的作用 4、和环境变量相关的命令 5、环境变量的组织方式 6、获取环境变量的方式 1)通过环境参数表获取 2)通过系统调用获取或设置环境变…

微信小程序开发组件和API(附源代码演示)

微信小程序组件参考文档:https://developers.weixin.qq.com/miniprogram/dev/component/ 微信开发者工具下载网址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html 小程序开发指南:https://developers.weixin.qq…

Langchain框架深度剖析:解锁大模型-RAG技术的无限潜能,引领AI应用新纪元

文章目录 前言一、Langchain 框架概述二、大模型-RAG技术原理三、应用示例1.RAG案例一(私有文档直接读取-问答)2.RAG案例二(Vue上传文件结合文件内容回答问题)3.RAG案例三(Vue秒传文件结合文件内容回答问题&#xff09…

C语言——预处理详解(上)

目录 引言 预定义符号 define 定义常量 #define 定义宏 带有副作用的宏参数 宏替换的规则 宏和函数的对比 引言 在C语言编程中,预处理是编译前的关键步骤,它负责处理如宏定义、条件编译和文件包含等指令。今天我们来学习一下有关C语言——预处理…

洛谷 3道 函数 题目 题解 (超详细)

题目目录: No.1 B2137 判决素数个数 No.2 B2138 最大质因子序列 No.3 B2140 二进制分类 OK,开始正文! 第一题: B2137 判决素数个数 题目描述 求 X,Y 之间的素数个数(包括 X 和 Y)。 输入…

LB-8100A 推拉力测试机精密推拉力试验机

LB-8100A 多功能推拉力测试机广泛应于与 LED 封装测试、IC 半导体封 装测试、TO 封装测试、IGBT 功率模块封装测试、光电子元器件封装测试、汽 车领域、航天航空领域、军工产品测试、研究机构的测试及各类院校的测试 研究等应用。 多功能推拉力测试机精密推拉力试验机 *设备硬件…

地热模拟软件opengeosys-OGS安装和学习1

1.下载地址 官网:https://www.opengeosys.org/ 界面Gina:https://discourse.opengeosys.org/t/gina-version-3-24/175 https://teambeam.bgr.de/my/drive/folder/68(注意下载压缩包,有些注册表需要处理) 2.处理 下…

视频汇聚平台智能边缘分析一体机分析平台摄像头异常位移算法识别检测

智能边缘分析一体机在摄像头异常位移检测方面扮演着关键角色,它利用先进的图像处理技术和机器学习算法来实时监测摄像头状态,判断是否发生了非预期的位移。下面是智能边缘分析一体机如何检测摄像头异常位移的详细步骤: 1. 图像帧对比&#x…

内部排序(二路归并、基数、计数)

【内部排序(插入、交换、选择)】 一、二路归并排序 1. 算法思想与实现步骤 1)算法思想: 二路归并排序是一种分治算法。它将待排序的序列分为两个子序列,分别对这两个子序列进行排序,然后将两个已排序的子…

安美数字酒店宽带运营系统 weather.php 任意文件读取漏洞复现

0x01 产品简介 HiBOS酒店宽带运营系统是由安美世纪(北京)科技有限公司开发的一套专为酒店设计的宽带管理系统。该系统旨在提升酒店宽带服务的运营效率和安全性,为酒店客人提供稳定、高速、便捷的上网体验。 0x02 漏洞概述 安美数字酒店宽带运营系统 weather.php …