Mutation Observer API 突变监视接口数组
用来监视 DOM 变更。异步
DOM 的任何变更,好比节点的增减、属性的变更、文本内容的变更,这个 API 均可以获得通知函数
概念上,它很接近事件,能够理解为 DOM 发生变更就会触发 Mutation Observer 事件。spa
可是,Mutation Observer 与 事件 有一个本质不一样:code
Mutation Observer 有如下特色:server
Mutation Observer 构造函数对象
var box = document.getElementById("test_box");
// 1. 定义一个 监视器 实例
var mo = new MutationObserver(function(mutations, observer){ mutations.forEach(function(mutation){ console.log(mutation); }); });
// 2. 定义要监听的 类型集合 对象
var chgType = {
"childList": true, // 子节点变更 监视
"attributes": true, // 属性变更 监视
"characterData": true, // 节点内容 或者 节点文本 的变更
};
// 3. 启动监听
mo.observe(box, chgType);
.observe() 启动监视器blog
至少指定一种要监听的变更类型,不然报错接口
"childList": true, 子节点 变更事件
"attributes": true, 属性 变更
"characterData": true, 节点内容 或者 节点文本 变更
还可指定监听属性
"subtree": true, 是否同时监视该节点的全部后代节点
"attributeOldValue": true, 监视 attributes 变更时,是否须要记录变更前的属性值
"characterDataOldValue": true, 监视 characterData 变更时,是否须要记录变更前的属性值
"attributeFilter": 数组, 表示须要观察的特定属性(好比['class','src'])
var insertedNodes = [];
var mo = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { for (var i = 0; i < mutation.addedNodes.length; i++) insertedNodes.push(mutation.addedNodes[i]); }) });
mo.observe(document, { childList: true }); console.log(insertedNodes);
.disconnect(); 中止监视
.takeRecords(); 清除变更记录,即再也不处理未处理的变更____该方法返回变更记录的数组
// 保存全部没有被观察器处理的变更 var changes = mutationObserver.takeRecords();
MutationRecord 对象
DOM 每次发生变化,就会生成一条变更记录(MutationRecord 实例)。该实例包含了与变更相关的全部信息。
Mutation Observer 处理的就是一个个 MutationRecord 实例所组成的数组
type 观察的 突变类型(attributes、characterData 或者 childList)
target 发生突变的 DOM 节点
addedNodes 新增的 DOM 节点
removedNodes 删除的 DOM 节点
previousSibling 前一个同级节点,若是没有则返回 null
nextSibling 下一个同级节点,若是没有则返回 null
attributeName 发生突变的属性。若是设置了 attributeFilter,则只返回预先指定的属性
oldValue 突变前的值。这个属性只对 attribute 和 characterData 突变有效,若是发生 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 chgType = { 'childList': true, 'subtree': true }; mo.observe(document.body, chgType);
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);
(function(win){ 'use strict'; var doc = win.document; var MutationObserver = win.MutationObserver || win.WebKitMutationObserver; var targets = []; var mo; function isReadyOrNot(){ // 检查是否匹配已储存的节点 for(var i = 0; i < targets.length; i++){ var target = targets[i]; var elements = doc.querySelectorAll(target.selector); // 检查指定节点是否有匹配 for(var j = 0; j < elements.length; j++){ var element = elements[j]; // 确保回调函数只会对该元素调用一次 if(!element.isReady){ element.isReady = true; // 对该节点调用回调函数 target.fn.call(element, element); }; }; }; }; /**** 目标元素 只要在 DOM 上已加载, 则执行 fn ****/ win.eleReady = function(selector, fn){ // 储存选择器和回调函数 targets.push({ selector: selector, fn: fn }); if(!mo){ mo = new MutationObserver(isReadyOrNot); // 定义 突变监听器 mo.observe(doc.documentElement, { // 开始监听 document变化 childList: true, // 监听 子节点 subtree: true // 同时监听 后代节点 }); }; isReadyOrNot(); // 检查该节点是否已经在DOM中 }; })(window); eleReady('.foo', function(element){ // ... });