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