MutationObserver 监听DOM
介绍
MutationObserver
接口提供了监视对DOM树所做更改的能力。
构造函数
MutationObserver()
创建并返回一个新的MutationObserver
它会在指定的DOM发生变化时被调用。
new MutationObserver(callback)
:当每次DOM发生变化的时候都会触发callback。
等所有的DOM操作完成之后一次执行(异步)
方法
-
阻止 MutationObserver
实例继续接收的通知,直到再次调用其observe()
方法,该观察者对象包含的回调函数都不会再被调用。 -
配置
MutationObserver
在DOM更改匹配给定选项时,通过其回调函数开始接收通知。 -
从MutationObserver的通知队列中删除所有待处理的通知,并将它们返回到
MutationRecord
对象的新Array
中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>MutationObserver</title> </head> <body> <div id="simple" class="test"> simple </div> </body> <script> // mutations 变动数组 observer 观察器实例 var observer = new MutationObserver(function (mutations, observer) { mutations.forEach(function(mutation) { // 执行具体的操作 // 例如:页面劫持 console.log(mutation) }) }) // 开始监听页面根元素 html 变化 observer.observe(document.getElementById("simple"), { attributes: true, // 属性变动 characterData: true, // 节点内容或节点文本的变动 childList: true, // 子节点的变动 subtree: true, // 表示是否将观察器应用于该节点的所有后代节点 attributeOldValue: true, // 表示观察 attributes 变动时,是否需要记录变动前的属性值 characterDataOldValue: true, // 表示观察 characterData 变动时,是否需要记录变动前的值 attributeFilter: ["style"] // 数组,表示需要观察的特定属性 (比如: ["class", "src"]) }); // document.getElementById("simple").innerText = 123; document.getElementById("simple").firstChild.nodeValue="test"; // document.getElementById("simple").setAttribute("style", "background-color:blue; color:red; border:1px solid black"); // document.getElementById("simple").style.height = "123px"; // document.getElementById("simple").innerHTML = "<p>rrr</p>"; // // 停止观察, 调用该方法后,DOM 再发生变动,也不会触发观察器 // observer.disconnect(); // // 清除变动记录,即不再处理未处理的变动,改方法返回变动记录的数组。 // observer.takeRecords(); // // 保存所有没有被观察器处理的变动 // var changes = observer.takeRecords(); // console.log(changes, "changes"); // // 停止观察 // observer.disconnect(); // MutationRecord 对象 // type: 观察的变动类型 // target:发生变动的DOM节点 // addedNodes:新增的DOM节点 // removeNodes:删除的DOM节点 // previousSibling:前一个同级节点,如果没有则返回null // nextSibling:下一个同级节点,如果没有则返回null // attributeName:发生变动的属性。如果这只了 attributeFilter,则只返回预先指定的属性 // oldValue:变动前的值。这个属性只对 attribute和characterData变动有效,如果发生childList变动,则返回null </script> </html>
示例:水印不可删
<!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="content"></div> </body> <script> function drawCanvas() { let content = document.getElementById("content"); let divContainer = document.body.appendChild(document.createElement('div')); content.appendChild(divContainer); let waterMarkercanvas = document.createElement('canvas'); let context = waterMarkercanvas.getContext('2d'); divContainer.appendChild(waterMarkercanvas); divContainer.id = 'divContainer' let backgroundUrl = null; divContainer.style.height = window.innerHeight + 'px'; divContainer.style.width = window.innerWidth + 'px'; waterMarkercanvas.width = "400"; waterMarkercanvas.height = "400"; context.font = "20px"; context.textAlign = "center"; context.fillStyle = "#0000ff"; context.fillText("我是水印", 100, 100); backgroundUrl = waterMarkercanvas.toDataURL('image/png'); divContainer.style.backgroundImage = `url(${backgroundUrl})`; } drawCanvas(); let callback = (mutations) => { mutations.forEach(mutation => { console.log(mutation,"mutation"); if(mutation.removedNodes.length > 0 && mutation.removedNodes[0].id == "divContainer" && mutation.addedNodes.length <= 0) { setTimeout(function() { console.log("新增") drawCanvas(); }, 3000) } }); }; let observer = new MutationObserver(callback); observer.observe(document.getElementById("content"), { childList: true, // subtree: true }); console.log(document.getElementsByTagName("div")) setTimeout(function() { console.log("删除") document.getElementById("content").removeChild(document.getElementById("divContainer")); }, 3000) </script> </html>
-
防止运营劫持:监控
dom
,不在白名单内和安全标签内的script
或者iframe
,都给予remove
删除处理。
作者:带刀打天下
链接:https://www.jianshu.com/p/7129ce865f33
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。