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对象 是我们每修改一个就会在数组里面追加一个
})
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']
})
disconnect()方法用来停止观察
takeRecords()方法用来清除变动记录,即不再处理未处理的变动。该方法返回变动记录的数组。
属性 | 说明 | 默认值 |
---|---|---|
attributes | 设为 true 以观察受监视元素的属性值变更。 | 默认值为 false。 |
attributeFilter | 要监视的特定属性名称的数组。如果未包含此属性,则对所有属性的更改都会触发变动通知。 | 无默认值。 |
characterData | 设为 true 以监视指定目标节点或子节点树中节点所包含的字符数据的变化。 | 无默认值 |
childList | 设为 true 以监视目标节点(如果 subtree 为 true,则包含子孙节点)添加或删除新的子节点。 | 默认值为 false。 |
subtree | 的其他值也会作用于此子树下的所有节点,而不仅仅只作用于目标节点。 | 默认值为 false。 |
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),然后设定记录变动前的值。实际发生变动时,会将变动前的值显示在控制台。
网页加载的时候,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){
// ...
});
1 天前