如何监听dom的变动?
当 DOM 发生变动,会触发 MutationObserver 事件
var observer = new MutationObserver(callback)
文档:
developer.mozilla.org/zh-CN/docs/…
MutationObserver 优点
优化频繁操作dom的效率
举例来说,如果在文档中连续插入 1000 个段落(p元素),就会连续触发 1000 个插入事件,执行每个事件的回调函数,这很可能造成浏览器的卡顿;
而 MutationObserver 不同,只在 1000 个段落都插入结束后才会触发,而且只触发一次。
与事件的区别(概念上,接近事件)
事件:是同步触发。
当 DOM 发生变动,立刻会触发相应的事件;
MutationObserver :是异步触发
DOM 发生变动以后,并不会马上触发,而是要等到当前所有 DOM 操作都结束后才触发。
代码举例:
<!DOCTYPE html>
<html lang="en">
<meta charset="UTF-8">
<title>Title</title>
</head>
<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>
<button onclick="handleClick(1)">+1</button>
<button onclick="handleClick(-1)">-1</button>
</div>
<script>
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
</script>
</body>
</html>
实际应用:防止水印被删除或更改
用 MutationObserver 防止水印被删除或更改
const observer = new MutationObserver(() => {
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
完整的代码:(生成canvas水印图片,用 MutationObserver 防止水印被删除或更改)
<script>
function watermark (text1, text2) {
var canvas = document.createElement('canvas')
canvas.width = 150
canvas.height = 120
canvas.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)
var watermark = document.createElement('div')
const styleStr = `
position:fixed !important;
top:0 !important;
left:0 !important;
width:100vw !important;
height:100vh !important;
z-index:99 !important;
pointer-events:none !important;
background-repeat:repeat !important;
mix-blend-mode: multiply !important;
background-image:url('${canvas.toDataURL('image/png')}') !important`
watermark.setAttribute('style', styleStr)
watermark.classList.add('watermark')
document.appendChild(watermark)
const observer = new MutationObserver((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
watermark('qwer', '你是qwer')
</script>
码字不易,点赞鼓励