1、介绍
MutationObserver
是一个构造函数,可以用来监听某个节点的变化,当节点发生变化时,可以执行一些回调函数。
它不会立即执
行,需要调用MutationObserver的observe方法
,传入你想要监听的节点,以及一些配置
,然后当节点发生变化时,就会执行你传入的回调函数。
2、基本使用
- MutationObserver的构造函数的入参是
数组
- MutationObserver的observe函数,第一个参数是
目标节点
,第二个参数是配置项
- childList:布尔值,默认为 false。设置为 true 时,表示观察目标节点的
子节点列表的变化
,包括添加或删除子节点。 - attributes:布尔值,默认为 false。设置为 true 时,表示观察目标节点的
属性
变化。 - characterData:布尔值,默认为 false。设置为 true 时,表示观察目标
节点文本内容
的变化。 - subtree:布尔值,默认为 false。设置为 true 时,表示观察
目标节点以及其所有后代节点
的变化。 - attributeFilter:
数组
,用于指定要观察的属性名
。如果不设置此选项,则观察目标节点的所有属性变化。 - attributeOldValue:布尔值,默认为 false。如果设置为 true,则在回调函数的 MutationRecord 对象中包含被
修改属性的旧值
。 - characterDataOldValue:布尔值,默认为 false。如果设置为 true,则在回调函数的 MutationRecord 对象中包含被
修改的文本节点的旧值
。
- childList:布尔值,默认为 false。设置为 true 时,表示观察目标节点的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="target" style="height: 400px;">
</div>
<script>
// MutationObserver 接口提供了监视对 DOM 树所做更改的能力。
var target = document.getElementById('target');
function observe() {
var observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
console.log(mutation, mutation.type);
// mutation 是一个对象,包含:变化类型、旧值、目标元素等信息
});
});
observer.observe(target, {
attributes: true, // 布尔值,默认为 false。设置为 true 时,表示观察目标节点的属性变化。
childList: true, //布尔值,默认为 false。设置为 true 时,表示观察目标节点的子节点列表的变化,包括添加或删除子节点。
characterData: true, // 布尔值,默认为 false。设置为 true 时,表示观察目标节点文本内容的变化
subtree: true,// 布尔值,默认为 false。设置为 true 时,表示观察目标节点以及其所有后代节点的变化。
attributeOldValue: true,// 布尔值,默认为 false。如果设置为 true,则在回调函数的 MutationRecord 对象中包含被修改属性的旧值。
});
}
observe()
setTimeout(() => {
target.style.height = '100px'
target.style.backgroundColor = 'red'
}, 2000)
</script>
</body>
</html>
3、使用场景
- 监听水印被删除
- 监听某个DOM被动态添加或删除
- 监听文本内容的变化
- Vue 的 nextTick
举例水印被删除
<script>
// MutationObserver 接口提供了监视对 DOM 树所做更改的能力。
// var target = document.getElementById('target');
// function observe() {
// var observer = new MutationObserver((mutations) => {
// mutations.forEach((mutation) => {
// console.log(mutation, mutation.type);
// // mutation 是一个对象,包含:变化类型、旧值、目标元素等信息
// });
// });
// observer.observe(target, {
// attributes: true, // 布尔值,默认为 false。设置为 true 时,表示观察目标节点的属性变化。
// childList: true, //布尔值,默认为 false。设置为 true 时,表示观察目标节点的子节点列表的变化,包括添加或删除子节点。
// characterData: true, // 布尔值,默认为 false。设置为 true 时,表示观察目标节点文本内容的变化
// subtree: true,// 布尔值,默认为 false。设置为 true 时,表示观察目标节点以及其所有后代节点的变化。
// attributeOldValue: true,// 布尔值,默认为 false。如果设置为 true,则在回调函数的 MutationRecord 对象中包含被修改属性的旧值。
// });
// }
// observe()
// setTimeout(() => {
// target.style.height = '100vh'
// target.style.backgroundColor = 'red'
// }, 2000)
// 调用
__canvasWM({
content: '呆呆狗'
})
// canvas 实现 watermark
function __canvasWM({
container = document.body,
width = '200px',
height = '150px',
textAlign = 'center',
textBaseline = 'middle',
font = "20px microsoft yahei",
fillStyle = 'rgba(184, 184, 184, 0.8)',
content = '请勿外传',
rotate = '30',
zIndex = 1000
} = {}) {
var args = arguments[0];
var canvas = document.createElement('canvas');
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
var ctx = canvas.getContext("2d");
ctx.textAlign = textAlign;
ctx.textBaseline = textBaseline;
ctx.font = font;
ctx.fillStyle = fillStyle;
ctx.rotate(Math.PI / 180 * rotate);
ctx.fillText(content, parseFloat(width) / 2, parseFloat(height) / 2);
var base64Url = canvas.toDataURL();
const watermarkDiv = document.createElement("div");
watermarkDiv.setAttribute('style', `
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
z-index:${zIndex};
pointer-events:none;
background-repeat:repeat;
background-image:url('${base64Url}')`);
watermarkDiv.id = "watermarkDiv"
container.style.position = 'relative';
container.insertBefore(watermarkDiv, container.firstChild);
}
let watermarkEl = document.querySelector('#watermarkDiv')
var watermarkElObserver = new MutationObserver((mutations) => {
console.log(mutations, '发生变化');
mutations.forEach((mutation) => {
// 方案1
// if (!document.body.contains(document.querySelector('#watermarkDiv'))) {
// alert('水印被删除')
// }
// 方案2
if (Array.from(mutation.removedNodes).includes(watermarkEl)) {
alert('水印被删除')
}
});
});
// 如果目标元素是动态生成的或者它的父节点被替换,可能导致观察器无法正确识别目标元素的删除。你可以检查一下DOM结构是否发生了变化。
watermarkElObserver.observe(document.body, {
subtree: true,// 布尔值,默认为 false。设置为 true 时,表示观察目标节点以及其所有后代节点的变化。
childList: true, //布尔值,默认为 false。设置为 true 时,表示观察目标节点的子节点列表的变化,包括添加或删除子节点。
attributes: true,
});
</script>