深入理解 Observer
浏览器为开发者提供了功能丰富的 Observer,在这篇文章中,我们将学习这些常见的浏览器 Observer,剖析它们的作用、用法以及它们在 Web 开发中的应用场景。
IntersectionObserver
IntersectionObserver
用于监听元素在视口中的可见比例变化。
常用API
IntersectionObserver(callback[, options])
:创建新的实例,传入变动时的回调函数和配置对象。observe(target)
:开始观察指定目标元素,传入目标元素。unobserve(target)
:停止观察指定目标元素。disconnect()
:停止观察,断开与所有目标元素的关联。
基本用法
- // 选择需要观察变动的节点
- const target = document.getElementById('some');
- const options = {
- root: rootTarget, // 可以是一个祖先级对象,这时,主要的是针对局部的滚动效果。如果构造函数未传入 root 或其值为null,则默认使用顶级文档的视口。
- rootMargin: '0px', // 视口的偏移值,相当于扩大视口的范围。
- threshold: 0.5 // 当被观察者进入视口百分之多少时触发观察者
- };
- const intersectionObserver = new IntersectionObserver((entries, observer) => {
- entries.forEach(entry => {
- console.log(entry);
- });
- }, options);
- // 开始观察目标节点
- intersectionObserver.observe(target);
- threshold默认值是0,表示:刚进入时就触发观察者的回调函数;完全离开时,在触发观察的回调
- 当threshold的值是1,表示:当被监听元素完全进入视图在触发观察者的回调函数
常见场景
- 监听图片懒加载
- const observer = new IntersectionObserver(
- (entries, observer) => {
- if (entries[0].intersectionRatio > 0.1) {
- // 存在交叉,出现在视区中
- }
- },
- {
- threshold: 0.1,
- }
- )
- const target = document.querySelector('img')
- observer.observe(target)
ResizeObserver
ResizeObserver 是一个 JavaScript API,用于监视元素的大小变化,每次大小更改时都会向观察者传递通知。
- const resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {
- entries.forEach(entry => {
- // do something...
- })
- })
- resizeObserver.observe(elem)
常用API
ResizeObserver(callback)
:创建新的实例,传入尺寸变化时的回调函数。observe(target)
:开始观察指定目标元素,传入目标元素。unobserve(target)
:停止观察指定目标元素。disconnect()
:停止观察,断开与所有目标元素的关联。
ResizeObserverEntry
- borderBoxSize:一个对象,当运行回调时,该对象包含着正在观察元素的新边框盒的大小。
- contentBoxSize:一个对象,当运行回调时,该对象包含着正在观察元素的新内容盒的大小。
- devicePixelContentBoxSize:一个对象,当运行回调时,该对象包含着正在观察元素的新内容盒的大小(以设备像素为单位)。
- contentRect:一个对象,当运行回调时,该对象包含着正在观察元素新大小的 DOMRectReadOnly 对象。
- target:对正在观察 Element 或 SVGElement 的引用
备注:内容盒是放置内容的盒子,即边框盒减去内边距和边框宽度。边框盒包含内容、内边距和边框。
常用场景
- 监听尺寸变化适配视区
MutationObserver
MutationObserver
用于监听DOM对象的变更,包括节点属性的变化、子节点的增删改等。
常用API
MutationObserver(callback)
:创建新的实例,传入变更时的回调函数。observe(target[, options])
:开始观察指定目标节点,传入目标节点和配置对象。disconnect()
:停止观察,断开与所有目标节点的关联。takeRecords()
:从 MutationObserver 的通知队列中删除所有待处理的通知,并将它们返回到 MutationRecord 对象的新 Array 中。
基本用法
- // 选择需要观察变动的节点
- const targetNode = document.getElementById("some");
- // 观察器的配置(需要观察什么变动)
- const config = {
- attributes: true, // 观察所有监听的节点属性值的变化
- childList: true, // 监听 target 节点中发生的节点的新增与删除
- subtree: true, // 监听以 target 为根节点的整个子树。包括子树中所有节点的属性
- characterData: true // 监听声明的 target 节点上所有字符的变化。
- };
- // 当观察到变动时执行的回调函数
- const callback = function (mutationsList, observer) {
- console.log(mutationsList);
- };
- // 创建一个观察器实例并传入回调函数
- const observer = new MutationObserver(callback);
- // 开始观察目标节点
- observer.observe(targetNode, config);
- // 之后,可停止观察
- observer.disconnect();
PerformanceObserver
PerformanceObserver
用于监听浏览器的性能事件,便于处理性能相关信息。
常用API
PerformanceObserver(callback)
:创建新的实例,传入性能事件发生时的回调函数。observe(options)
:开始观察指定类型的性能事件,传入配置对象,指定entryTypes。disconnect()
:停止观察,断开与所有性能事件的关联。
常见entryTypes
mark
:标记时间戳的事件。measure
:performance.measure触发的事件。frame
:网页渲染的事件。navigation
:导航的事件,例如页面加载或重新加载。
基本用法
- function perf_observer(list, observer) {
- console.log(list);
- }
- const observer = new PerformanceObserver(perf_observer);
- observer.observe({ entryTypes: ["measure"] });
常用场景
- 首次内容绘制
- export function observePaintFCP() {
- const entryHandler = (list) => {
- for (const entry of list.getEntries()) {
- if (entry.name === 'first-contentful-paint') {
- observer.disconnect();
- }
- }
- };
- const observer = new PerformanceObserver(entryHandler);
- observer.observe({ entryTypes: ['paint'] });
- }
ReportingObserver
ReportingObserver用于监听浏览器报告的事件,例如废弃API,过时特性,网络错误。
常用API
ReportingObserver(callback)
:创建新的实例,传入报告事件发生时的回调函数。observe(options)
:开始观察指定类型的报告事件,传入配置对象,指定types。disconnect()
:停止观察,断开与所有报告事件的关联。
常见报告事件类型
deprecation
:废弃API的事件。intervention
:浏览器干预的事件。crash
:浏览器崩溃的事件。error
:一般的错误事件。
基本用法
- const reportingObserver = new ReportingObserver(reports => {
- reports.forEach(report => {
- console.log(report);
- });
- });
- reportingObserver.observe({ types: ["deprecation", "intervention"] });