MutationObserver
MutationObserver
给开发者们提供了一种能在某个范围内的DOM树发生变化时作出适当反应的能力.该API设计用来替换掉在DOM3事件规范中引入的Mutation事件.
构造函数
MutationObserver()
该构造函数用来实例化一个新的Mutation观察者对象.
MutationObserver(
function callback
);
参数
-
该回调函数会在指定的DOM节点(目标节点)发生变化时被调用.在调用时,观察者对象会传给该函数两个参数,第一个参数是个包含了若干个
MutationRecord
对象的数组,第二个参数则是这个观察者对象本身.
callback
实例方法
void observe( |
void disconnect(); |
Array takeRecords(); |
observe()
给当前观察者对象注册需要观察的目标节点,在目标节点(还可以同时观察其后代节点)发生DOM变化时收到通知.
void observe(
Node target,
optional MutationObserverInit options
);
参数
- 观察该节点是否会发生DOM变化.
-
一个
MutationObserverInit
对象,指定要观察的DOM变化类型.
target
options
disconnect()
让该观察者对象停止观察指定目标的DOM变化.直到再次调用其observe()
方法,该观察者对象包含的回调函数都不会再被调用.
void disconnect();
takeRecords()
清空观察者对象的
记录队列,并返回里面的内容.
Array takeRecords();
返回值
返回一个包含了MutationRecord
s对象的数组.
MutationObserverInit
MutationObserverInit是一个用来配置观察者对象行为的对象,该对象可以拥有下面这些属性
:
childList
,
attributes
, 或者
characterData
三个属性中必须至少有一个为
true
.否则,会抛出异常"An invalid or illegal string was specified".
属性 | 描述 |
childList | 如果需要观察目标节点的子节点(新增了某个子节点,或者移除了某个子节点),则设置为true . |
attributes | 如果需要观察目标节点的属性节点(新增或删除了某个属性,以及某个属性的属性值发生了变化),则设置为true . |
characterData | 如果目标节点为characterData节点(一种抽象接口,具体可以为文本节点 ,注释节点,以及处理指令节点) 时,也要观察该节点的文本内容是否发生变化,则设置为true . |
subtree | 除了目标节点,如果还需要观察目标节点的所有后代节点(观察目标节点所包含的整棵DOM树上的上述三种节点变化),则设置为true . |
attributeOldValue | 在 |
characterDataOldValue | 在characterData 属性已经设为true的前提下,如果需要将发生变化的 characterData 节点之前的 文本内容记录下来(记录到下面MutationRecord对象的oldValue属性中),则设置为true . |
attributeFilter | 一个属性名数组(不需要指定命名空间),只有该数组中包含的属性名发生变化时才会被观察到,其他名称的属性发生变化后会被忽略. |
MutationRecord
MutationRecord
对象会作为第一个参数传递给观察者对象包含的回调函数,该对象有下面这些属性:
属性 | 类型 | 描述 |
type | String | 如果是属性发生变化,则返回attributes .如果是一个CharacterData 节点发生变化,则返回characterData ,如果是目标节点的某个子节点发生了变化,则返回childList. |
target |
| 返回此次变化影响到的节点,具体返回那种节点类型是根据type值的不同而不同的 . 如果type 为attributes ,则返回发生变化的属性节点所在的元素节点,如果type 值为characterData ,则返回发生变化的这个characterData 节点.如果type 为childList ,则返回发生变化的子节点的父节点. |
addedNodes |
| 返回被添加的节点,或者为null . |
removedNodes |
| 返回被删除的节点,或者为null . |
previousSibling |
| 返回被添加或被删除的节点的前一个兄弟节点,或者为null . |
nextSibling |
| 返回被添加或被删除的节点的后一个兄弟节点,或者为null . |
attributeName | String | 返回变更属性的本地名称,或者为null . |
attributeNamespace | String | 返回变更属性的命名空间,或者为null . |
oldValue | String | 根据 |
例子
下面的例子来自这篇博文.
// 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();
假设target
为当前文档中某个已知的节点,observer
为某个已经实例化的MutationObserver
观察者对象,则:
observer.observe(target, {childList:true}) //childList属性只观察子节点的新建与删除,子节点本身的任何变化都不会去理会 target.appendChild(document.createElement("div")) //添加了一个元素子节点,触发回调函数. target.appendChild(document.createTextNode("foo")) //添加了一个文本子节点,触发回调函数. target.removeChild(target.childNodes[0]) //移除第一个子节点,触发回调函数. target.childNodes[0].appendChild(document.createElement("div")) //为第一个子节点添加一个子节点,不会触发回调函数,如果需要触发,则需要设置subtree属性为true. observer.observe(target, {childList:true,subtree:true}) //subtree属性让观察行为进行"递归",这时,以target节点为根节点的整棵DOM树发生的变化都可能会被观察到 observer.observe(document, {childList:true,subtree:true}) //如果target为document或者document.documentElement,则当前文档中所有的节点添加与删除操作都会被观察到 observer.observe(document, {childList:true,attributes:true,characterData:true,subtree:true}) //当前文档中几乎所有类型的节点变化都会被观察到(包括属性节点的变化和文本节点的变化等) observer.observe(target, {childList:true}) //假设此时target的outHTML内容为<div>foo<div>,则: target.childNodes[0].data = "bar" //不会触发回调函数,因为childList只观察节点的新建与删除,而这里target节点的子节点仍然只有一个,没有多,没有少 observer.observe(target, {childList:true,characterData:true}) //加上characterData属性,允许观察文本节点的变化,行不行? target.childNodes[0].data = "bar" //还是不会触发回调函数,因为发生变化的是target节点的子节点,我们目前的目标节点只有一个,就是target. observer.observe(target, {childList:true,characterData:true,subtree:true}) //加上subtree属性,观察所有后代节点 target.childNodes[0].data = "bar" //触发了回调函数,发生变化的是target节点的文本子节点(必须同时有characterData和subtree属性,才能观察到一个元素目标节点里的文本内容的变化) observer.observe(target, {attributes:true}) //只观察目标节点的属性节点 target.setAttribute("foo","bar") //不管foo属性存在不存在,都会触发回调函数 target.setAttribute("foo","bar") //即使前后两次的属性值一样,还是会触发回调函数 target.removeAttribute("foo") //移除foo属性节点,触发回调函数 target.removeAttribute("foo") //不会触发回调函数,因为已经没有属性节点可移除了 observer.observe(target, {attributes:true,attributeFilter:["bar"]}) //指定要观察的属性名 target.setAttribute("foo","bar") //不会触发回调函数,因为attributeFilter数组不包含"foo" target.setAttribute("bar","foo") //触发了回调函数,因为attributeFilter数组包含了"bar"
refer to https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver