mutationobserver监听dom变化

更新日期: 2023-02-27阅读: 1.5k标签: 监听

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

DOM 的变动会触发 Mutation Observer 事件,但与事件不同的是,Mutation Observer 是异步触发,也就是说,Mutation Observer 事件会在所有的 DOM 操作完成后才触发一次。


实例

回调函数接受两个参数,一个是变动的数组,一个是观察器实例

let observer = new MutationObserver(function (mutations, observer) {
mutations.forEach(function(mutation) {
console.log(mutation)
})
// 返回一个我们监听到的MutationRecord对象
// MutationRecord对象 是我们每修改一个就会在数组里面追加一个
})



方法

1. observe

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

第一个是需要观察的节点

第二个是配置对象,配置项的前三项必须至少设置一项,否则会报错

var container = document.querySelector('.container');

observer.observe(container, {
  childList:true, // 子节点的变动(指新增,删除或者更改)
  attributes:true, // 属性的变动
  characterData:true, // 节点内容或节点文本的变动
  subtree:false, // 是否将该观察器应用于该节点的所有后代节点
  attributeOldValue:false, // 观察attributes变动时,是否需要记录变动前的属性值
  characterDataOldValue:false, // 表示观察characterData变动时,是否需要记录变动前的值
  attributeFilter:[], // 表示需要观察的特定属性,如 ['class','src']
})

2.disconnect

disconnect()方法用来停止观察

3. takeRecords

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


可监听的属性(配置)

属性说明默认值
attributes设为 true 以观察受监视元素的属性值变更。默认值为 false。
attributeFilter要监视的特定属性名称的数组。如果未包含此属性,则对所有属性的更改都会触发变动通知。无默认值。
characterData设为 true 以监视指定目标节点或子节点树中节点所包含的字符数据的变化。无默认值
childList设为 true 以监视目标节点(如果 subtree 为 true,则包含子孙节点)添加或删除新的子节点。默认值为 false。
subtree的其他值也会作用于此子树下的所有节点,而不仅仅只作用于目标节点。默认值为 false。


MutationRecord

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

MutationRecord中包含的信息

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


应用场景:

  • App中用WebView显示一个本地html文件
  • html文件下载JavaScript然后用JSONP显示一个网页
  • 这个网页中实际内容是用iframe显示的一个表单
  • 表单中有一个Close按钮
  • 需求就是点击Close按钮的时候关掉App中引入WebView的页面

简单来说就是想捕捉iframe里面的Close按钮的点击事件。因为捕捉到了点击事件就可以把这个事件传入到App层,App就可以关闭页面。

子元素的变动

下面的例子说明如何读取变动记录。

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节点)的子节点的变动,subtree属性指定监听还包括后代节点。因此,任意一个网页元素一旦生成,就能立刻被监听到。

下面的代码,使用MutationObserver对象封装一个监听 DOM 生成的函数。

(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){
  // ...
});

链接: https://fly63.com/article/detial/12359

原生js监听浏览器后退按钮的事件方法

js监听浏览器后退按钮的事件首先我们要了解浏览器的history。可以使用pushState方法往history里增加url链接,并且提供popstate事件监测从history栈里弹出url。既然有提供popstate事件监测,那么我们就可以进行监听。

使用 vue 实例更好的监听事件

文章举例说明一下在 vue 中如何更好的监听浏览器事件。原文介绍了一种新增 vue 实例的方法,单独监听事件。这样代码书写较为简练,容易管理。

js 按键监听事件(keydown event)

监听全局键盘按下事件,例如监听全局回车事件;监听某个组件键盘按下事件,例如监听id为btn的button组件的回车按下事件;如果是要监听组合键,例如监听ctrl+c

Vue2.0解决watch对象属性变化监听不到问题

在项目中遇到一个问题,父组件向子组件传值,子组件监听传入对象的某个属性的时候,发现子组件使用deep watch都不能监听到属性的变化。今天终于在网上找到了答案,在这里把方法记录下来

vue中的watch的用法

在vue中,使用watch来响应数据的变化。下面代码是watch简单的用法:监听值变化;监听处理函数,在所监听的数据后面直接加字符串形式的方法名;监听对象变化

jQuery常见事件的监听方式

在 Web 页面经常会有各种事件发生,事件发生后需要进行一些特定处理,即执行特定的函数或者语句。这就需要对事件进行监听,监听事件的常见方式有以下三种,本人将通过实例来具体介绍。

uniapp监听网络状态 - 判断是否有网络

由于新机首次安装app的时候会出现:请求网络权限“是否允许使用数据”,如果用户很长时间没点击允许,就会出现app内接口请求永远返回失败的情况,需要用户清掉APP重新打开才能正常请求使用。

Js如何移除事件监听器

在运行时清理你的代码是构建高效、可预测的应用程序,没有商量余地的部分。在JavaScript中,实现这一目标的方法之一是很好地管理事件监听器,尤其是当不再需要时移除它们。

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!