(91)Wangdao.com第二十四天_Mutation Observer API 突變監視器

Mutation Observer API 突變監視接口數組

用來監視 DOM 變更。異步

DOM 的任何變更,好比節點的增減屬性的變更文本內容的變更,這個 API 均可以獲得通知函數

概念上,它很接近事件,能夠理解爲 DOM 發生變更就會觸發 Mutation Observer 事件。spa

 

可是,Mutation Observer 與 事件 有一個本質不一樣:code

    • 事件是同步觸發,也就是說,DOM 的變更馬上會觸發相應的事件;
    • Mutation Observer 則是異步觸發,DOM 的變更並不會立刻觸發,而是要等到當前全部 DOM 操做都結束才觸發

 

Mutation Observer 有如下特色:server

    • 它等待全部腳本任務完成後,纔會運行(即異步觸發方式)。
    • 它把 DOM 變更記錄封裝成一個數組進行處理,而不是一條條個別處理 DOM 變更。
    • 它既能夠觀察 DOM 的全部類型變更,也能夠指定只觀察某一類變更。

 

Mutation Observer 構造函數對象

  • 使用
    • 使用 MutationObserver 構造函數,新建一個觀察器實例,同時指定這個實例的回調函數。
      • 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

  • 第一個參數是 所要觀察的DOM元素是article
  • 第二個參數是 所要觀察的變更類型        

至少指定一種要監聽的變更類型,不然報錯接口

"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 實例所組成的數組

  • MutationRecord 對象包含了 DOM 的相關信息,有以下屬性:

 

type        觀察的 突變類型(attributes、characterData 或者 childList)
target        發生突變的 DOM 節點
addedNodes        新增的 DOM 節點
removedNodes        刪除的 DOM 節點
previousSibling        前一個同級節點,若是沒有則返回 null
nextSibling        下一個同級節點,若是沒有則返回 null
attributeName        發生突變的屬性。若是設置了 attributeFilter,則只返回預先指定的屬性
oldValue        突變前的值。這個屬性只對 attribute 和 characterData 突變有效,若是發生 childList 突變,則返回 null

 

  • 實例: 觀察<body>的全部下級節點, 回調函數會在控制檯顯示全部變更的類型和目標節點
  • 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);
  • 實例: 屬性變更('attributes': true), 實際發生變更時,會將變更前的值顯示在控制檯。
  • 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);

 

  • 封裝: 目標元素 只要在 DOM 上已加載, 則執行 fn
  • (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){
        // ...
    });
相關文章
相關標籤/搜索