JS 实时监听页面元素变化

549人浏览 / 0人评论

参考

https://www.cnblogs.com/ygunoil/p/13402712.html

说明

// 选择需要观察变动的节点
const targetNode = document.getElementById('some-id');
 
// 观察器的配置(需要观察什么变动)
const config = { attributes: true, childList: true, subtree: true };
 
// 当观察到变动时执行的回调函数
const callback = function(mutationsList, observer) {
    // Use traditional 'for loops' for IE 11
    for(let mutation of mutationsList) {
        if (mutation.type === 'childList') {
            console.log('A child node has been added or removed.');
        }
        else if (mutation.type === 'attributes') {
            console.log('The ' + mutation.attributeName + ' attribute was modified.');
        }
    }
};
 
// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(callback);
 
// 以上述配置开始观察目标节点
observer.observe(targetNode, config);
 
// 之后,可停止观察
observer.disconnect();

1、MutationObserver所观察的DOM变动(即上面代码的option对象),包含以下类型:

  • childList:子元素的变动;
  • attributes:属性的变动;
  • characterData:节点内容或节点文本的变动;
  • subtree:所有下属节点(包括子节点和子节点的子节点)的变动;

想要观察哪一种变动类型,就在option对象中指定它的值为true。

需要注意的是,不能单独观察subtree变动,必须同时指定childList、attributes和characterData中的一种或多种。

除了变动类型,option对象还可以设定以下属性:

  • attributeOldValue:值为true或者为false。如果为true,则表示需要记录变动前的属性值。
  • characterDataOldValue:值为true或者为false。如果为true,则表示需要记录变动前的数据值。
  • attributesFilter:值为一个数组,表示需要观察的特定属性(比如['class', 'str'])。

2、disconnect方法用来停止观察。发生相应变动时,不再调用回调函数。

mo.disconnect();

3、takeRecord方法用来清除变动记录,即不再处理未处理的变动。

mo.takeRecord();

MutationRecord 对象

DOM对象每次发生变化,就会生成一条变动记录。这个变动记录对应一个MutationRecord对象,该对象包含了与变动相关的所有信息。Mutation Observer进行处理的一个个变动对象所组成的数组。

MutationRecord对象包含了DOM的相关信息,有如下属性:

  • type:观察的变动类型(attribute、characterData或者childList)。
  • target:发生变动的DOM对象。
  • addedNodes:新增的DOM对象。
  • removeNodes:删除的DOM对象。
  • previousSibling:前一个同级的DOM对象,如果没有则返回null。
  • nextSibling:下一个同级的DOM对象,如果没有就返回null。
  • attributeName:发生变动的属性。如果设置了attributeFilter,则只返回预先指定的属性。
  • oldValue:变动前的值。这个属性只对attribute和characterData变动有效,如果发生childList变动,则返回null。

示例

编辑文章时同步生成目录

function setCatalogue() {
    let target = document.getElementsByClassName("ck-content")[0];
    let h2nbsp = "";
    let h3nbsp = "    ";
    let h4nbsp = "        ";
    $(".right-navigate-list").empty();
    $(target).children().each(function (index, element) {
        let tagName = $(this).get(0).tagName;
        if (tagName.substr(0, 1).toUpperCase() === "H") {
            let contentH = $(this).html();
            let markid = "mark-" + tagName + "-" + index.toString();
            $(this).attr("id", markid);
            let nbsp = "";
            if (tagName.indexOf("3") !== -1) {
                nbsp = h3nbsp;
            } else if (tagName.indexOf("4") !== -1) {
                nbsp = h4nbsp;
            }
            $(".right-navigate-list").append("<li><a href='#" + markid + "' title='" + contentH + "' target='_self'><span>" + nbsp + "</span><i class='bi-arrow-bar-right' aria-hidden='true'></i>" + contentH + "</a></li>");
        }
    });
}
window.onload = function (){
    setCatalogue()
    let callback = function(records) {
        setCatalogue();
        // records.map(function(record) {
        //     console.log('mutation type:', record.type);
        //     console.log('mutation target:', record.target);
        // });
    };
    let mo  = new MutationObserver(callback);
    let options = {
        childList: true,
        subtree: true
    };
    let target = document.getElementsByClassName("ck-content")[0];
    mo.observe(target, options);
};

其他

实例1 - 子元素的变动
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 options = {
    childList: true,
    subtree: true
};
// 观察body元素的所有下级元素(childList表示观察子元素,subtree表示观察子元素的下级元素)的变动。回调函数会在控制台显示所有变动的类型和目标元素。
mo.observe(document.body, options);
实例2 - 属性变动
var callback = function(records) {
    records.map(function(record) {
        console.log('previous attribute:', record.oldValue);
    });
};
 
var mo =  new MutationObserver(callback);
 
var element = document.querySelector('#app');
var options = {
    attribute: true,
    attributeOldValue: true
};
 
mo.observe(element, options);

全部评论