(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){
        // ...
    });
相关文章
相关标签/搜索