# MutationObserver监听DOM变更应用

> MutationObserver接口提供了实时检测DOM属性或节点变更时调用。犹如单页面应用中的数据双向绑定监听其数据变更一般。只要属性或节点变更，就执行其他操作。

Author: DeathGhost
Published: 2020-07-16 22:58:02
Category: javascript
Canonical: https://www.deathghost.cn/article/javascript/79
Keywords: MutationObserver, Web API, JavaScript, 监听, 观察, DOM属性, DOM节点, 变更, 实时检测, 实时监听

MutationObserver API 用来监视 DOM 变更。DOM 的任何变动，比如节点的增减、属性的变动、文本内容的变动，这个 API 都可以得到通知。

类似一个监听事件，不同之处是异步触发，也就是说，当DOM操作结束后方才调用。

![MutationObserver 监听DOM属性节点变更](https://www.deathghost.cn/public/upload/article/2020/07/16/1594915078253580.jpg)

MutationObserver 监听DOM属性节点变更

## 示例应用场景

Web页面中我们通过按钮点击赋值到一个&ldquo;第三方&rdquo;提供&ldquo;模块&rdquo;，无需再次调用接口渲染HTML，仅需对属性赋值。那么&ldquo;第三方&rdquo;JavaScript文件监听到元素属性变更自动执行请求查询数据且渲染。

以下示例进为属性变更。例如：一个Web页面中：

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>DEMO</title>
</head>
<body>
    <h1>新码笔记</h1>
    <div>
        <input type="text" value="18888888888"/>
        <input type="button" value="查询"/>
    </div>
    <main>页面主题内容</main>
    <footer>By DeathGhost</footer>
</body>
</html>
我们需要在页面中插入&ldquo;第三方组件&rdquo;，提供HTML内容如下：

<numberList></numberList>
<script src="xxx.js"></script>
页面中仅在点击&ldquo;查询&rdquo;时对&ldquo;第三方&rdquo;标签元素属性赋值即可。

那么我们首先将其引入到Web页面中。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>DEMO</title>
</head>
<body>
    <h1>新码笔记</h1>
    <div>
        <input type="text" value="18888888888"/>
        <input type="button" value="查询"/>
    </div>
    <div>
        <!-- 开始::第三方组件包裹 -->
        <numberList data-number=""></numberList>
        <script src="xxx.js"></script>
        <!-- 结束::第三方组件包裹 -->
    </div>
    <main>页面主题内容</main>
    <footer>By DeathGhost</footer>
</body>
</html>
点击查询时，我们将value赋值给numberList元素，xxx.js就会通过MutationObserver接口监听其属性值对其执行查询渲染。

## 方法介绍

disconnect() 阻止 MutationObserver 实例继续接收的通知，直到再次调用其observe()方法，该观察者对象包含的回调函数都不会再被调用。

observe() 配置MutationObserver在DOM更改匹配给定选项时，通过其回调函数开始接收通知。

takeRecords() 从MutationObserver的通知队列中删除所有待处理的通知，并将它们返回到MutationRecord对象的新Array中。

## MutationObserver特点

- 等待所有脚本任务完成后，才会运行（即异步触发方式）。

- 把 DOM 变动记录封装成一个数组进行处理，而不是一条条个别处理 DOM 变动。

- 既可以观察 DOM 的所有类型变动，也可以指定只观察某一类变动。

## 实际应用示例

使用时，首先使用MutationObserver构造函数，新建一个观察器实例，同时指定这个实例的回调函数。

const observer = new MutationObserver(callback);
上面代码中的回调函数，会在每次 DOM 变动后调用。该回调函数接受两个参数，第一个是变动数组，第二个是观察器实例，下面是一个例子。

// ***.js 文件
const callBack = function(mutationsList, observer) {
    for(let mutation of mutationsList) {
        if (mutation.type === 'attributes') {
            renderDOM();
        }
    }
};

const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
const observer = new MutationObserver(callBack);
observer.observe(wrap, {
    attributes: true,
    childList: false,
    characterData: false,
    attributeFilter: ['data-number'],
    attributeOldValue: true,
});

async function renderDOM() {
  // Request && Render ...
}
结合上述应用场景，我们需要观察的是属性"data-number"的变更（上述特点3），所以如上所示。

最后，兼容性大家参考CANIUSE，使用根据实际情况而定。小小示例以做笔记，详情参考[这里](https://dom.spec.whatwg.org/#mutationobserver)。

## Related

- Previous: [高阶函数替换JavaScript中的循环](https://www.deathghost.cn/article/javascript/75)
- Next: [JS原生的深拷贝API structuredClone()](https://www.deathghost.cn/article/javascript/120)
