前端-如何监听dom的变动-防止水印被删除或更改
如何监听dom的变动?
当 DOM 发生变动,会触发 MutationObserver 事件
var observer = new MutationObserver(callback)
MutationObserver 优点
优化频繁操作dom的效率
- 举例来说,如果在文档中连续插入 1000 个段落(p元素),就会连续触发 1000 个插入事件,执行每个事件的回调函数,这很可能造成浏览器的卡顿;
- 而 MutationObserver 不同,只在 1000 个段落都插入结束后才会触发,而且只触发一次。
与事件的区别(概念上,接近事件)
- 事件:是同步触发。
- 当 DOM 发生变动,立刻会触发相应的事件;
- MutationObserver :是异步触发
- DOM 发生变动以后,并不会马上触发,而是要等到当前所有 DOM 操作都结束后才触发。
代码举例:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="someElement"><div>111</div><div>222</div><div>3333</div></div><script>function handleClick (type) {const targetNode = document.querySelector("#someElement");if (type < 0) {targetNode.removeChild(targetNode.lastElementChild)} else {targetNode.appendChild(document.createElement('br'))}}</script><div><button onclick="handleClick(1)">+1</button><button onclick="handleClick(-1)">-1</button></div><script>// MutationObserver 部分代码const targetNode = document.querySelector("#someElement");const callback = (obj) => {console.log(obj)}const observer = new MutationObserver(callback);observer.observe(targetNode, {childList: true, // 观察目标子节点的变化,是否有添加或者删除attributes: true, // 观察属性变动subtree: true // 观察后代节点,默认为 false})</script></body></html>
实际应用:防止水印被删除或更改
用 MutationObserver 防止水印被删除或更改
// 此方法是防止用户通过 开发者工具 修改样式/或直接删除 祛除水印const observer = new MutationObserver(() => {const wmInstance = document.querySelector('.watermark') // 获取到你的水印domif (!wmInstance) {console.log('水印被删除了!!!')document.body.appendChild(watermark)return}if (wmInstance.getAttribute('style') !== styleStr) {console.log('改水印样式了!!!')wmInstance.setAttribute('style', styleStr)}})observer.observe(document.body, {childList: true, // 观察目标子节点的变化,是否有添加或者删除attributes: true, // 观察属性变动subtree: true // 观察后代节点,默认为 false})
完整的代码:(生成canvas水印图片,用 MutationObserver 防止水印被删除或更改)
<script>function watermark (text1, text2) {var canvas = document.createElement('canvas')canvas.width = 150canvas.height = 120canvas.style.display = 'none'var shuiyin = canvas.getContext('2d')// 控制文字的旋转角度和上下位置shuiyin.rotate(-20 * Math.PI / 180)shuiyin.translate(-50, 20)// 文字颜色shuiyin.fillStyle = '#dedede'// 文字样式shuiyin.font = '100 16px "PingFang SC", "Microsoft YaHei", Arial, sans-serif 'shuiyin.fillText(text1, canvas.width / 3, canvas.height / 2)shuiyin.fillText(text2, canvas.width / 3, canvas.height / 2 + 20)/* 新建一个用于填充canvas水印的标签,之所以没有直接在body上添加,是因为z-index对个别内容影响,才考虑的不用body */var watermark = document.createElement('div')const styleStr = `position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:99;pointer-events:none;background-repeat:repeat;mix-blend-mode: multiply;background-image:url('${canvas.toDataURL('image/png')}')`watermark.setAttribute('style', styleStr)watermark.classList.add('watermark')document.body.appendChild(watermark)// 此方法是防止用户通过控制台修改样式去除水印效果/* MutationObserver 是一个可以监听DOM结构变化的接口。 */const observer = new MutationObserver((aa) => {// console.dir(aa)const wmInstance = document.querySelector('.watermark')if (!wmInstance) {console.log('水印被删除了!!!')document.body.appendChild(watermark)return}if (wmInstance.getAttribute('style') !== styleStr) {console.log('改水印样式了!!!')wmInstance.setAttribute('style', styleStr)}})observer.observe(document.body, {childList: true, // 观察目标子节点的变化,是否有添加或者删除attributes: true, // 观察属性变动subtree: true // 观察后代节点,默认为 false})}watermark('qwer', '你是qwer')</script>
码字不易,点赞鼓励
