Mutation Observer 笔记(转)

这篇具有很好参考价值的文章主要介绍了Mutation Observer 笔记(转)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Mutation Observer API 

Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。

概念上,它很接近事件,可以理解为 DOM 发生变动就会触发 Mutation Observer 事件。但是,它与事件有一个本质不同:事件是同步触发,也就是说,DOM 的变动立刻会触发相应的事件;Mutation Observer 则是异步触发,DOM 的变动并不会马上触发,而是要等到当前所有 DOM 操作都结束才触发。

这样设计是为了应付 DOM 变动频繁的特点。举例来说,如果文档中连续插入1000个<p>元素,就会连续触发1000个插入事件,执行每个事件的回调函数,这很可能造成浏览器的卡顿;而 Mutation Observer 完全不同,只在1000个段落都插入结束后才会触发,而且只触发一次。

Mutation Observer 有以下特点。

  • 它等待所有脚本任务完成后,才会运行(即异步触发方式)。
  • 它把 DOM 变动记录封装成一个数组进行处理,而不是一条条个别处理 DOM 变动。
  • 它既可以观察 DOM 的所有类型变动,也可以指定只观察某一类变动。

MutationObserver 构造函数 

使用时,首先使用MutationObserver构造函数,新建一个观察器实例,同时指定这个实例的回调函数。

var observer = new MutationObserver(callback);

上面代码中的回调函数,会在每次 DOM 变动后调用。该回调函数接受两个参数,第一个是变动数组,第二个是观察器实例,下面是一个例子。

var observer = new MutationObserver(function (mutations, observer) {
  mutations.forEach(function(mutation) {
    console.log(mutation);
  });
});

MutationObserver 的实例方法

observe() 

observe()方法用来启动监听,它接受两个参数。 

  • 第一个参数:所要观察的 DOM 节点
  • 第二个参数:一个配置对象,指定所要观察的特定变动
var article = document.querySelector('article');
var  options = {
  'childList': true,
  'attributes':true
} ;
observer.observe(article, options);

上面代码中,observe()方法接受两个参数,第一个是所要观察的DOM元素是article,第二个是所要观察的变动类型(子节点变动和属性变动)。

观察器所能观察的 DOM 变动类型(即上面代码的options对象),有以下几种。

  • childList:子节点的变动(指新增,删除或者更改)。
  • attributes:属性的变动。
  • characterData:节点内容或节点文本的变动。

想要观察哪一种变动类型,就在option对象中指定它的值为true。需要注意的是,至少必须同时指定这三种观察的一种,若均未指定将报错。

除了变动类型,options对象还可以设定以下属性:

  • subtree:布尔值,表示是否将该观察器应用于该节点的所有后代节点。
  • attributeOldValue:布尔值,表示观察attributes变动时,是否需要记录变动前的属性值。
  • characterDataOldValue:布尔值,表示观察characterData变动时,是否需要记录变动前的值。
  • attributeFilter:数组,表示需要观察的特定属性(比如['class','src'])。
// 开始监听文档根节点(即<html>标签)的变动
mutationObserver.observe(document.documentElement, {
  attributes: true,
  characterData: true,
  childList: true,
  subtree: true,
  attributeOldValue: true,
  characterDataOldValue: true
});

对一个节点添加观察器,就像使用addEventListener()方法一样,多次添加同一个观察器是无效的,回调函数依然只会触发一次。如果指定不同的options对象,以后面添加的那个为准,类似覆盖。

下面的例子是观察新增的子节点。

var insertedNodes = [];
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    for (var i = 0; i < mutation.addedNodes.length; i++) {
      insertedNodes.push(mutation.addedNodes[i]);
    }
  });
  console.log(insertedNodes);
});
observer.observe(document, { childList: true, subtree: true });

disconnect(),takeRecords()

disconnect()方法用来停止观察。调用该方法后,DOM 再发生变动,也不会触发观察器。

observer.disconnect();

takeRecords()方法用来清除变动记录,即不再处理未处理的变动。该方法返回变动记录的数组。

observer.takeRecords();
// 保存所有没有被观察器处理的变动
var changes = mutationObserver.takeRecords();
// 停止观察
mutationObserver.disconnect();

MutationRecord 对象

DOM 每次发生变化,就会生成一条变动记录(MutationRecord 实例)。该实例包含了与变动相关的所有信息。Mutation Observer 处理的就是一个个MutationRecord实例所组成的数组。

 MutationRecord对象包含了DOM的相关信息,有如下属性:

  • type:观察的变动类型(attributescharacterData或者childList)。
  • target:发生变动的DOM节点。
  • addedNodes:新增的DOM节点。
  • removedNodes:删除的DOM节点。
  • previousSibling:前一个同级节点,如果没有则返回null
  • nextSibling:下一个同级节点,如果没有则返回null
  • attributeName:发生变动的属性。如果设置了attributeFilter,则只返回预先指定的属性。
  • oldValue:变动前的值。这个属性只对attributecharacterData变动有效,如果发生childList变动,则返回null

应用示例(子元素的变动)
下面的例子说明如何读取变动记录。

var callback = function (records){
  records.map(function(record){
    console.log('Mutation type: ' + record.type);
    console.log('Mutation target: ' + record.target);
  });
};
var mo = new MutationObserver(callback);
var option = {
  'childList': true,
  'subtree': true
};
mo.observe(document.body, option);

上面代码的观察器,观察<body>的所有下级节点(childList表示观察子节点,subtree表示观察后代节点)的变动。回调函数会在控制台显示所有变动的类型和目标节点

应用示例(属性的变动)
下面的例子说明如何追踪属性的变动。

var callback = function (records) {
  records.map(function (record) {
    console.log('Previous attribute value: ' + record.oldValue);
  });
};
var mo = new MutationObserver(callback);
var element = document.getElementById('#my_element');
var options = {
  'attributes': true,
  'attributeOldValue': true
}
mo.observe(element, options);

上面代码先设定追踪属性变动('attributes': true),然后设定记录变动前的值。实际发生变动时,会将变动前的值显示在控制台。

取代 DOMContentLoaded 事件

网页加载的时候,DOM 节点的生成会产生变动记录,因此只要观察 DOM 的变动,就能在第一时间触发相关事件,也就没有必要使用DOMContentLoaded事件。 

var observer = new MutationObserver(callback);
observer.observe(document.documentElement, {
  childList: true,
  subtree: true
});

上面代码中,监听document.documentElement(即网页的<html>HTML 节点)的子节点的变动,subtree属性指定监听还包括后代节点。因此,任意一个网页元素一旦生成,就能立刻被监听到。

下面的代码,使用MutationObserver对象封装一个监听 DOM 生成的函数。文章来源地址https://www.toymoban.com/news/detail-679547.html

(function(win){
  'use strict';
  var listeners = [];
  var doc = win.document;
  var MutationObserver = win.MutationObserver || win.WebKitMutationObserver;
  var observer;
  function ready(selector, fn){
    // 储存选择器和回调函数
    listeners.push({
      selector: selector,
      fn: fn
    });
    if(!observer){
      // 监听document变化
      observer = new MutationObserver(check);
      observer.observe(doc.documentElement, {
        childList: true,
        subtree: true
      });
    }
    // 检查该节点是否已经在DOM中
    check();
  }
  function check(){
  // 检查是否匹配已储存的节点
    for(var i = 0; i < listeners.length; i++){
      var listener = listeners[i];
      // 检查指定节点是否有匹配
      var elements = doc.querySelectorAll(listener.selector);
      for(var j = 0; j < elements.length; j++){
        var element = elements[j];
        // 确保回调函数只会对该元素调用一次
        if(!element.ready){
          element.ready = true;
          // 对该节点调用回调函数
          listener.fn.call(element, element);
        }
      }
    }
  }
  // 对外暴露ready
  win.ready = ready;
})(this);
// 使用方法
ready('.foo', function(element){
  // ...
});

到了这里,关于Mutation Observer 笔记(转)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【设计模式】观察者模式Observer Pattern

    目录 遇到问题 梳理需求 观察者模式的实现 JDK中的实现 当一个对象发生修改时,需要通知多方。 很自然就会想到回调,这个就是观察者模式的核心,观察者模式可以将大量的回调解耦,从而使代码更加优雅。 意图: 定义对象间的一种一对多的依赖关系,当一个对象的状态

    2024年02月22日
    浏览(42)
  • 行为型-观察者模式(Observer Pattern)

    详细介绍观察者模式(Observer Pattern),并说明优缺点与使用场景: 观察者模式是一种行为型设计模式,它定义了对象之间的一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖它的对象都会自动收到通知并更新。该模式包含两个核心角色:被观察者(Subj

    2024年02月15日
    浏览(64)
  • 【设计模式——学习笔记】23种设计模式——观察者模式Observer(原理讲解+应用场景介绍+案例介绍+Java代码实现)

    有一个天气预报项目,需求如下: 气象站可以将每天测量到的温度、湿度、气压等等以公告的形式发布出去(比如发布到自己的网站或第三方) 需要设计开放型API,便于其他第三方也能接入气象站获取数据 提供温度、气压、湿度的接口 测量数据更新时,要能实时的通知给第三

    2024年02月14日
    浏览(38)
  • 「观察者(Observer)」设计模式 Swift实现

    观察者设计模式(Observer Pattern)是一种行为型设计模式,它定义了对象之间的一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会受到通知并自动更新。 在这种模式中,被观察者对象(Subject)存储其观察者对象(Observer)列表,并提供了用

    2024年02月16日
    浏览(39)
  • 设计模式二十:观察者模式(Observer Pattern)

    定义了一种一对多的依赖关系,允许多个观察者(也称为订阅者)对象同时监听一个主题对象,当主题对象发生变化时,所有依赖于它的观察者都会收到通知并自动更新。 观察者模式的使用场景 观察者模式在许多场景中都可以发挥作用,特别是在需要解耦和实现对象间动态

    2024年02月12日
    浏览(39)
  • (三)行为模式:7、观察者模式(Observer Pattern)(C++示例)

    目录 1、观察者模式(Observer Pattern)含义 2、观察者模式的UML图学习 3、观察者模式的应用场景 4、观察者模式的优缺点 (1)优点: (2)缺点 5、C++实现观察者模式的实例 1、观察者模式(Observer Pattern)含义 观察者模式(Observer)定义了一种一对多的依赖关系,让多个观察者

    2024年02月09日
    浏览(42)
  • 设计模式——观察者模式(Observer Pattern)+ Spring相关源码

    类型:行为型模式 目的:当一个对象的状态发生改变时,其所有依赖者(观察者)都会收到通知并自动更新。 2.1.1 定义观察者 2.1.2 定义被观察对象 2.1.3 使用 2.2.1 观察者接口Observer 2.2.1 被观察者对象Observable 2.3.1 观察者 2.3.2 被观察者 创建型模式 结构型模式 1、设计模式——

    2024年02月06日
    浏览(48)
  • 观察者设计模式(Observer Design Pattern)[论点:概念、组成角色、相关图示、示例代码、框架中的运用、适用场景]

            观察者设计模式(Observer Design Pattern)是一种行为型设计模式,它定义了一种对象间的一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生改变时,通知所有观察者对象,使它们能够自动更新。 主题(Subject):主题是一个抽象类或

    2023年04月24日
    浏览(46)
  • ts:简单实现 mobx 的观察者模式 observable

    mobx 状态管理器 订阅者: 管理 变化后 回调的函数列表 观察者:将传入的 数据监听 起来,并且在 有变化时 , 执行 订阅者管理的 函数列表

    2024年02月12日
    浏览(54)
  • Mutation Observer 笔记(转)

    Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。 概念上,它很接近事件,可以理解为 DOM 发生变动就会触发 Mutation Observer 事件。但是,它与事件有一个本质不同:事件是同步触发,也就是说,

    2024年02月11日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包