1 概述

Mutation observer 是用于代替 Mutation events 作为观察DOM树结构发生变化时,做出相应处理的API。为什么要使用mutation observer 去代替 mutation events 呢,我们先了解一下mutation events

Mutation Events

Mutation events 是在 DOM3中定义,用于监听DOM树结构变化的事件

它简单的用法如下:

document.getElementById('list').addEventListener("DOMSubtreeModified", function(){
console.log('列表中子元素被修改');
}, false);

Mutation 事件列表

  • DOMAttrModified
  • DOMAttributeNameChanged
  • DOMCharacterDataModified
  • DOMElementNameChanged
  • DOMNodeInserted
  • DOMNodeRemoved
  • DOMNodeInsertedIntoDocument
  • DOMSubtreeModified

其中DOMNodeRemoved,DOMNodeInserted 和 DOMSubtreeModified 分别用于 监听元素子项的删除,新增,修改(包括删除和新增),
DOMAttrModified 是监听元素属性的修改,并且能够提供具体的修改动作。

Mutation Events遇到的问题
  • 浏览器兼容性问题
    IE9不支持Mutation Events
    Webkit内核不支持DOMAttrModified特性,
    DOMElementNameChanged和DOMAttributeNameChanged 在Firefox上不被支持。
  • 性能问题
    1.Mutation Events是同步执行的,它的每次调用,都需要从事件队列中取出事件,执行,然后事件队列中移除,期间需要移动队列元素。如果事件触发的较为频繁的话,每一次都需要执行上面的这些步骤,那么浏览器会被拖慢。
    2.Mutation Events本身是事件,所以捕获是采用的是事件冒泡的形式,如果冒泡捕获期间又触发了其他的MutationEvents的话,很有可能就会导致阻塞Javascript线程,甚至导致浏览器崩溃。

Mutation Observer

Mutation Observer 是在DOM4中定义的,用于替代 mutation events 的新API,它的不同于events的是,所有监听操作以及相应处理都是在其他脚本执行完成之后异步执行的,并且是所以变动触发之后,将变得记录在数组中,统一进行回调的,也就是说,当你使用observer监听多个DOM变化时,并且这若干个DOM发生了变化,那么observer会将变化记录到变化数组中,等待一起都结束了,然后一次性的从变化数组中执行其对应的回调函数。

Mutation Observer 的浏览器兼容范围

兼容性

2 方法

构造函数

用来实例化一个Mutation观察者对象,其中的参数是一个回调函数,它是会在指定的DOM节点发送变化后,执行的函数,并且会被传入两个参数,一个是变化记录数组(MutationRecord),另一个是观察者对象本身

new MutationObserver(function(records, itself){});
observe

在观察者对象上,注册需要观察的DOM节点,以及相应的参数

void observe(Node target, optional MutationObserverInit options)

其中的可选参数 MutationObserverInit的属性如下:

childLIst 观察目标节点的子节点的新增和删除。
attributes 观察目标节点的属性节点(新增或删除了某个属性,以及某个属性的属性值发生了变化)。
characterData 如果目标节点为characterData节点(一种抽象接口,具体可以为文本节点,注释节点,以及处理指令节点)时,也要观察该节点的文本内容是否发生变化
subtree 观察目标节点的所有后代节点(观察目标节点所包含的整棵DOM树上的上述三种节点变化)
attributeOldValue 在attributes属性已经设为true的前提下, 将发生变化的属性节点之前的属性值记录下来(记录到下面MutationRecord对象的oldValue属性中)
characterDataOldValue 在characterData属性已经设为true的前提下,将发生变化characterData节点之前的文本内容记录下来(记录到下面MutationRecord对象的oldValue属性中)
attributeFilter 一个属性名数组(不需要指定命名空间),只有该数组中包含的属性名发生变化时才会被观察到,其他名称的属性发生变化后会被忽略想要设置那些删选参数的话,

如果想要使用哪个参数的话,就将其值设定为true

disconnect

暂定在观察者对象上设置的节点的变化监听,直到重新调用observe方法

takeRecords

在观察者对象上调用takeRecords 会返回 其观察节点上的变化记录(MutationRecord)数组
其中MutationRecord数组也会作为,观察者初始化时的回调函数的第一个参数
其包含的属性如下:

type 如果是属性发生变化,则返回attributes.如果是一个CharacterData节点发生变化,则返回characterData,如果是目标节点的某个子节点发生了变化,则返回childList.
target 返回此次变化影响到的节点,具体返回那种节点类型是根据type值的不同而不同的,如果type为attributes,则返回发生变化的属性节点所在的元素节点,如果type值为characterData,则返回发生变化的这个characterData节点.如果type为childList,则返回发生变化的子节点的父节点.
addedNodes 返回被添加的节点
removedNodes 返回被删除的节点
previousSibling 返回被添加或被删除的节点的前一个兄弟节点
nextSibling 返回被添加或被删除的节点的后一个兄弟节点
attributeName 返回变更属性的本地名称
oldValue 根据type值的不同,返回的值也会不同.如果type为attributes,则返回该属性变化之前的属性值.如果type为characterData,则返回该节点变化之前的文本数据.如果type为childList,则返回null

3 使用实例

// Firefox和Chrome早期版本中带有前缀
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver
// 选择目标节点
var target = document.querySelector('#some-id');
// 创建观察者对象
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});
});
// 配置观察选项:
var config = { attributes: true, childList: true, characterData: true }
// 传入目标节点和观察选项
observer.observe(target, config);
// 随后,你还可以停止观察
observer.disconnect();

4 参考链接

[1].MDN Mutation Observer
[2].将突变事件和属性更改事件迁移到突变观察者

文/falm(简书作者)
原文链接:http://www.jianshu.com/p/b5c9e4c7b1e1
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

MutationObserver 监听DOM树变化的更多相关文章

  1. MutationObserver 监听 DOM 树变化

    MutationObserver 是用于代替 MutationEvents 作为观察 DOM 树结构发生变化时,做出相应处理的 API .为什么要使用 MutationObserver 去代替 Mut ...

  2. js动态监听dom变化

    原生js 动态监听dom变化,根据不同的类型绑定不同的处理逻辑 // Firefox和Chrome早期版本中带有前缀   var MutationObserver = window.MutationO ...

  3. JS监听DOM结构变化

    在做一个微博的接入,需要判断微博是否被关注,要检查微博标签的DIV是否有“已关注”的字符,但这个DIV的内容是微博JSSDK动态生成.$("#id").html()是获取不到我想要 ...

  4. jquery实时监听输入框值变化

    在做web开发时候很多时候都需要即时监听输入框值的变化,以便作出即时动作去引导浏览者增强网站的用户体验感.而采用onchange时间又往往是在输入框失去焦点(onblur)时候触发,有时候并不能满足条 ...

  5. angular的路由和监听路由的变化和用户超时的监听

    先看两篇博客:http://camnpr.com/javascript/1652.html 这一篇博客是重点中的重点:                   http://www.tuicool.com ...

  6. vue监听页面大小变化重新刷新布局

    在项目中由于某些div元素在布局的时候需要初始化宽高,因为当浏览器缩小屏幕的时候需要重新刷新页面视图. 分析思路: 1.在store中创建state,用于保存当前浏览器的宽.高值. 2.在mounte ...

  7. js实时监听dom尺寸变化

    开发过程中总会遇到dom节点尺寸变化,去做一些相应的逻辑,第一想到的应该是用$(window).resize()去做,但是这个是监听浏览器窗口的所以这个时候要用 ResizeObserver Resi ...

  8. HTML5 oninput实时监听输入框值变化的完美方案

    在网页开发中经常会碰到需要动态监听输入框值变化的情况,如果使用 onkeydown.onkeypress.onkeyup 这个几个键盘事件来监测的话,监听不了右键的复制.剪贴和粘贴这些操作,处理组合快 ...

  9. 【转载】实时监听输入框值变化的完美方案:oninput & onpropertychange

    oninput 是 HTML5 的标准事件,对于检测 textarea, input:text, input:password 和 input:search 这几个元素通过用户界面发生的内容变化非常有 ...

随机推荐

  1. 《Lua程序设计》第3章 表达式 学习笔记

    3.1 算术操作符“+”(加法).“-”(减法).“*”(乘法).“/”(除法).“^”(指数).“%”(取模).3.2 关系运算符< > <= >= == ~=3.3 逻辑操 ...

  2. 《C++ Primer Plus》第17章 输入、输出和文件 学习笔记

    流是进出程序的字节流.缓冲区是内存中的临时存储区域,是程序与文件或其他I/O设备之间的桥梁.信息在缓冲区和文件之间传输时,将使用设备(如磁盘驱动器)处理效率最高的尺寸以大块数据的方式进行传输.信息在缓 ...

  3. android中:/system/bin/sh: : No such file or directory错误

    将一个raspberry下编译好的可执行文件放在android的system/bin下,修改为777权限,运行,出现下面的错误: /system/bin/sh: XXX: No such file o ...

  4. Malab 常用数学函数

    l        三角函数和双曲函数 名称 含义 名称 含义 名称 含义 sin 正弦 csc 余割 atanh 反双曲正切 cos 余弦 asec 反正割 acoth 反双曲余切 tan 正切 ac ...

  5. 清空Cookie

    function delCookie() { ; i < cookies.length; i++) { try { document.cookie = cookies[i] + "=0 ...

  6. 剑指offer——49

    丑数 因子只含2,3,5的数称为丑数. 怎么求第K大的丑数呢.K可以为10^7 最简单的做法是,对每个数判断是否为丑数. 复杂度为O( n * log(n) ),理论上是不行的. uglys[i] 来 ...

  7. c++ 函数的默认参数

    /** * @file test.cpp * @author chenjiashou(chenjiashou@baidu.com) * @date 2017/08/20 15:54:27 * @ver ...

  8. MFC 三种消息

    在MFC应用程序中传输的消息有三种类型:窗口消息.命令消息和控件通知. (1)窗口消息:WM_XXX 窗口消息(Window Message)一般与窗口的内部运作有关,如:创建窗口.绘制窗口和销毁窗口 ...

  9. php-config

    php-config php-config 是一个简单的命令行脚本用于获取所安装的 PHP 配置的信息. 在编译扩展时,如果安装有多个 PHP 版本,可以在配置时用 --with-php-config ...

  10. 画一条0.5px的边

    1.scale方法 { height: 1px; transform: scaleY(0.5); transform-origin: 50% 100%; // 要指定origin值, 要不然会模糊 c ...