详细告诉你MutationObserver监听DOM元素的各种情况

978 阅读2分钟

MutationObserver

MutationObserver 观察器可以观察目标节点的子节点、属性和文本内容等变化。具体来说,它能够观察以下三种类型的变化:

  1. childList:指目标节点的子节点发生变化,例如新增或删除一个子元素。
  2. attributes:指目标节点的属性发生变化,例如修改一个属性的值。
  3. characterData:指目标节点或其子节点的文本内容发生变化,例如修改了一个文本节点的内容。

除了上述三种基本类型之外,MutationObserver 还提供了一些其他的配置选项,以便更精细地控制观察器的行为。这些选项包括:

  1. subtree:表示是否观察目标节点的后代节点中任意一个节点的变化(默认为 false)。
  2. attributeOldValue:如果设置为 true,则在属性变化时记录之前的属性值(默认为 false)。
  3. characterDataOldValue:如果设置为 true,则在字符数据变化时记录之前的值(默认为 false)。
  4. attributeFilter:一个数组,其中每个元素都是要观察的属性名。为空数组则表示观察所有属性的变化。

我们可以根据具体需求选择相应的配置选项,并在回调函数中处理相应的业务逻辑。需要注意的是,不同类型的变化会触发不同类型的 MutationRecord 对象,而在回调函数中我们可以获取到这些对象,并通过它们的属性来判断变化的具体类型和内容。

示例代码

例1:监听元素属性变化

// 需要被监听的元素
const targetNode = document.getElementById('target');
​
// 创建一个 MutationObserver 对象
const observer = new MutationObserver(function(mutationsList, observer) {
    // 迭代所有的变更记录
    for (let mutation of mutationsList) {
        if (mutation.type === 'attributes') {
            console.log(`属性 ${mutation.attributeName} 的值发生了变化`);
        }
    }
});
​
// 开始观察目标节点
observer.observe(targetNode, { attributes: true });

例2:监听元素子节点的变化

// 需要被监听的元素
const targetNode = document.getElementById('target');
​
// 创建一个 MutationObserver 对象
const observer = new MutationObserver(function(mutationsList, observer) {
    // 迭代所有的变更记录
    for (let mutation of mutationsList) {
        if (mutation.type === 'childList') {
            console.log(`元素的子节点发生了变化`);
        }
    }
});
​
// 开始观察目标节点
observer.observe(targetNode, { childList: true });

例3:监听元素子节点及属性的变化

// 需要被监听的元素
const targetNode = document.getElementById('target');
​
// 创建一个 MutationObserver 对象
const observer = new MutationObserver(function(mutationsList, observer) {
    // 迭代所有的变更记录
    for (let mutation of mutationsList) {
        if (mutation.type === 'childList') {
            console.log(`元素的子节点发生了变化`);
        } else if (mutation.type === 'attributes') {
            console.log(`属性 ${mutation.attributeName} 的值发生了变化`);
        }
    }
});
​
// 开始观察目标节点
observer.observe(targetNode, { childList: true, attributes: true });

例4:监听指定属性的变化

// 需要被监听的元素
const targetNode = document.getElementById('target');
​
// 创建一个 MutationObserver 对象
const observer = new MutationObserver(function(mutationsList, observer) {
    // 迭代所有的变更记录
    for (let mutation of mutationsList) {
        if (mutation.type === 'attributes' && mutation.attributeName === 'data-name') {
            console.log(`属性 data-name 的值发生了变化,新值为 ${mutation.target.getAttribute('data-name')}`);
        }
    }
});
​
// 开始观察目标节点
observer.observe(targetNode, { attributes: true, attributeFilter: ['data-name'] });

例5:监听所有 DOM 变化

// 需要被监听的元素
const targetNode = document.documentElement;
​
// 创建一个 MutationObserver 对象
const observer = new MutationObserver(function(mutationsList, observer) {
    // 迭代所有的变更记录
    for (let mutation of mutationsList) {
        console.log(`发生了 ${mutation.type} 类型的变化`);
    }
});
​
// 开始观察目标节点
observer.observe(targetNode, { childList: true, attributes: true, subtree: true });