现代浏览器支持的不同类型的观察者

编辑推荐:诚征广告商金主入驻此广告位置,如有感兴趣的金主,欢迎邮件至:airenliao@gmail.com咨询相关合作事宜!!!(^_^)

特别声明:本文来源于@Jitendra Kasaudhan的《Different Types Of Observers Supported By Modern Browsers》一文。

在深入了解现代浏览器支持的观察者之前,让我们试着先了解什么观察者是什么。

观察者是什么

观察者(Observer)是一个观察或注意事物的程序。观察者可以观察浏览器中发生的某些活动并做出相应的响应。观察者类似于狗,观察某些活动,并提醒我们发生了一些不寻常的事情。一旦我们为某些活动获取到狗发出的警告时,我们有责任采取相应的行动。

使用观察者我们可以观察浏览器中发生的不同类型的活动(Activity),并采取必要的行动。比如,可以观察一个视频是否在视窗中显示,并启用自动播放;比如从父DOM元素中添加或删除子元素;比如一个盒了元素的大小尺寸发生变化等等。

以下是现代浏览器支持的四种不同类型的观察者:

  • Intersection Observer
  • Mutation Observer
  • Resize Observer
  • Performance Observer

IntersectionObserver

它用于观察两个HTML DOM元素之间的交集。当DOM进入或离开可见的视窗(Visible Viewport)时,在DOM中观察一个元素是很有用的。下面描述了IntersectionObserver的一些用例。

  • 当一个元素在视窗中可见时,延迟加载图像或其他资淅
  • 识别广告的可见性并计算广告收入
  • 实现网站的无限滚动。当用户向下滚动页面时,不必要浏览不同的页面
  • 当一个元素在视窗中时,加载和自动播放、视频或动画

目前,Firefox和Chrome支持IntersectionObserver,但对于不支持的浏览器,可以找到对应的Polyfill。

使用IntersectionObserver API主要需要三个步骤:

  • 创建观察者
  • 定义要观察的目标对象
  • 定义回调事件

创建观察者

const options = {
    root: document.querySelector('.scrollContainer'),
    rootMargin: '0px',
    threshold: [0.3, 0.5, 0.8, 1]
}

const observer = new IntersectionObserver(handler, options)

[0.3]的阈值意味着,当目标元素在根元素指定的元素内可见30%时,调用处理函数。上面意味着当元素被30%50%80%100%可见时,将调用处理程序、回调函数。

定义要观察的目标对象

我们可以定义多个目标对象来观察。正如前面的例子所提到的,狗应该知道在提醒每个人之前应该观察什么。

任何目标元素都可以通过调用.observer(target)方法来观察。

const target = document.querySelector(“.targetBox”);
observer.observe(target);

定义回调事件

这是当一个人注意到某件不寻常的事情发生时的反应。当目标元素与根元素通过阈值相交时,就会触发回调函数。

function handler (entries, observer) { 
    entries.forEach(entry => {
        // 每个entry描述一个观察到的目标元素的交集变化

        // entry.boundingClientRect
        // entry.intersectionRatio
        // entry.intersectionRect
        // entry.isIntersecting
        // entry.rootBounds
        // entry.target
        // entry.time
    });
};

我已经准备了一个Demo,它使用IntersectionObserver来改变目标框的颜色。当用户滚动时,在可见区域内看到它。

MutationObserver

MutationObserver用于观察DOM元素的变化。可以观察到在父节点中添加或删除子节点、属性值或数据内容等变化。在MutationObserver之前,DOM更改事件由Mutation事件处理,比如DOMAttrModifiedDOMAttributeNameChangedDOMNodeInserted

MutationObserver被DOM3中定义的Mutation事件所替代。避免这些突变事件的实际原因是性能问题和跨浏览器支持。

这个新API的最大受众可能是构建JS框架的人员,主要是解决问题和创建交互。另一个用例将是使用框架来操作DOM,并且需要对这些修改进行有效的响应(而不需要设置setTimeout)。

这个API在不同的浏览器上都得到很好的支持。

同样的,MutationObserver的实现也需要三个步骤:

创建观察者

它可以通过调用它的构造函数和传递处理函数和配置选项来创建。我们有一个选项来指定我们想要跟踪或观察什么样的变化。

const config = {
    childList: true,
    attributes: true,
    characterData: true
};
const observer = new MutationObserver(handler);
  • childList: true,表示观察与子节点相关的变化
  • attributes:true,表示观察属性更改
  • characterData; true,表示观察目标元素的数据内容的变化

定义要观察的目标对象

observer.observe(...)方法接受应该被观察到的目标元素。

const parent = document.querySelector(“.parent”);
observer.observe(parent, config);

定义回调事件

根据在观察者创建过程中使用的配置,当目标元素中发生更改时,会执行回调函数。回调函数是用突变记来对象触发的,该对象包含目标元素中发生的突变类型。

function handler(mutationRecords, observer) {
    mutationRecords.forEach((mutationRecord) => {
        switch(mutationRecord.type) {
            case “childList”: //child node added or removed
            break;
            case “attributes”: // attribute changed
            break;
            default:
        }
    });
}

我已经准备了一个Demo。该Demo将触发MutationObserver的回调处理程序,每当添加或删除新的节点时,都会使用属性更改。

ResizeObserver

ResizeObserver允许我们观察DOM元素的内容矩形大小(widthheight)的变化,并做出相应的响应。它就像给元素添加document.onresize()window.resize()事件。不调整视窗大小而只改变元素的大小,这是很有用的。例如,添加新的子元素,将元素的display设置为none或类似可以改变元素大小的的事件。事实上,它只关注内容框(Content Box)变化。比如下面这些行为将会触发ResizeObserver的行为:

  • 当观察到的元素被插入或从DOM中删除时,观察将会触发
  • 当观察到的元素display值为none时,观察都会触发
  • 观察不会对未替换的内联元素(non-replaced inline element)触发
  • 观察不会由CSS的transform触发
  • 如果元素有显示,而且元素大小不是0,0,观察将会触发

ResizeObserver通知内容框的大小,如下图所示:

不幸的是,到目前为止仅有Chrome64+支持它,大多数浏览器都还不支持它。

同样的,ResizeObserver的使用也分为三步:

创建观察者

可以通过调用它的构造函数和传递处理函数来创建它。

const observer = new ResizeObserver(handler);

定义要观察的目标对象

定义目标对象,其大小的变化应该被观察到。

const child = document.querySelector(“.child”);
observer.observe(child);

定义回调事件

function handler (entries) {
    entries.forEach((entry) => {
        const size = entry.target.contentRect;
        console.log(`Element’s size: width: ${size.width} , height: ${size.height}`);
    });
}

比如下面这个Demo:

有关于ResizeObserver更详细的介绍,可以点击这里进行了解

PerformanceObserver

它主要用于观察性能时间轴(Performance Timeline),并在浏览器记录时通知新的性能条目。它可以用来度量浏览器和Node.js应用程序中某些性能指标。在浏览器中,我们可以使用Window对象作为window.PerformanceObserver,在Node.js应用程序中需要perf_hooks获得性能对象。比如,const {performance} = require('perf_hooks')。它在下列情况下是有用的。

  • 测量请求(Request)和响应(Response)之间的处理时间。(浏览器)
  • 在从数据库中检索数据时计算持续时间。(Node.js应用程序)
  • 抽象精确的时间信息,使用Paint Timing API,比如First Paint或First Contentful Paint时间
  • 使用“User Timing API”、"Navigation Timing API"、“Network Information API”、“Resource Timing API”和“Paint Timing API”访问性能指标

执行PerformanceObserver需要三个步骤:

创建观察者

可以通过调用它的构造函数和传递处理函数来创建它。

const observer = new PerformanceObserver(logger);

定义要观察的目标对象

observer.observe(...)方法接受可以观察到的有效的入口类型。这些输入类型可能属于各种性能API,比如User tming或Navigation Timing API。有效的entryType值:

  • "mark”: [USER-TIMING]
  • "measure": [USER-TIMING]
  • "navigation": [NAVIGATION-TIMING-2]
  • "resource": [RESOURCE-TIMING]

代码:

// subscribe to User-Timing events
const config = {
    entryTypes: [“mark”, “measure”]
};
observer.observe(config);

定义回调函数事件

当应用程序中使用观察到的事件时,会触发回调处理程序。

function getDataFromServer() {
    performance.mark(“startWork”); // see [USER-TIMING]
    doWork(); // Some developer code
    performance.mark(“endWork”);
    performance.measure(“start to end”, “startWork”, “endWork”);
    const measure = performance.getEntriesByName(‘start to end’)[0];
}

function logger(list, observer) {
    const entries = list.getEntries();
    entries.forEach((entry) => {
        console.log(“Name: “ + entry.name +
        “, Type: “ + entry.entryType +
        “, Start: “ + entry.startTime +
        “, Duration: “ + entry.duration + “\n”);
    });
}

比如下面这个Demo:

你可以随意使用一个PerformanceObserver API。当一个用户点击一个按钮时,它将标志着开始和结束的瞬间,并测量在3000ms之后的持续时间。可以在控制台中查看输出结果。

@Irina Shestak在2018年Asia的JSConf上就分享了有关于PerformanceObservers相关的主题,比如PerformanceObserver APINodeJs的perf_hooks API

如果你对这些观察者有任何想法、建议或相关改进,欢迎与我们一起分享。

扩展阅读

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

如需转载,烦请注明出处:https://www.w3cplus.com/javascript/different-types-of-observers-supported-by-modern-browsers.html

如需转载,烦请注明出处:https://www.w3cplus.com/javascript/different-types-of-observers-supported-by-modern-browsers.html

如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!

赏杯咖啡,鼓励他创作更多优质内容!
返回顶部