Front-end – How to listen for dom changes – prevent watermark from being deleted or changed

How do I listen for DOM changes?

Var observer = new MutationObserver(callback)

  • Documents: developer.mozilla.org/zh-CN/docs/…

MutationObserver advantages

Optimize the efficiency of frequent DOM manipulation

  • For example, if you insert 1000 paragraphs (P elements) in a row into the document, 1000 insert events will be fired continuously, executing the callback function for each event, which is likely to cause the browser to stall.
  • The MutationObserver, on the other hand, fires only once after all 1000 paragraphs have been inserted.

Difference from events (conceptually, close to events)

  • Event: Is triggered synchronously.
    • When the DOM changes, the corresponding event is triggered immediately.
  • MutationObserver: Is triggered asynchronously
    • DOM changes are not triggered immediately, but wait until all current DOM operations are complete.

Example code:

<! DOCTYPEhtml>
<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 partial code
    const targetNode = document.querySelector("#someElement");
    const callback = (obj) = > {
      console.log(obj)
    }
    const observer = new MutationObserver(callback);
    observer.observe(targetNode, {
      childList: true.// Check whether the target child node is added or removed
      attributes: true.// Observe attribute changes
      subtree: true     // Observe the descendant node, which defaults to false
    })
  </script>
</body>
</html>
Copy the code

Practical application: prevent watermark from being deleted or changed

Use MutationObserver to prevent the watermark from being removed or changed

// This method is to prevent the user from modifying the style through developer tools/or directly removing the watermark
const observer = new MutationObserver(() = > {
  const wmInstance = document.querySelector('.watermark') // Get your watermark dom
  if(! wmInstance) {console.log('Watermark is removed!! ')
    document.body.appendChild(watermark)
    return
  }
  if (wmInstance.getAttribute('style') !== styleStr) {
    console.log('Changed the watermark style!! ')
    wmInstance.setAttribute('style', styleStr)
  }
})
observer.observe(document.body, {
  childList: true.// Check whether the target child node is added or removed
  attributes: true.// Observe attribute changes
  subtree: true // Observe the descendant node, which defaults to false
})
Copy the code

Complete code :(generates canvas watermark image, using MutationObserver to prevent watermark from being deleted or changed)

<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')
    // Control the text rotation Angle and up and down position
    shuiyin.rotate(-20 * Math.PI / 180)
    shuiyin.translate(-50.20)
    // Text color
    shuiyin.fillStyle = '#dedede'
    // Text style
    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)
    /* Create a new tag to fill the canvas watermark. The body */ is not added directly because z-index affects individual content
    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)

    // This method is to prevent the user from using the console to change the style to remove the watermark effect
    /* MutationObserver is an interface that listens for changes in the DOM structure. * /
    const observer = new MutationObserver((aa) = > {
      // console.dir(aa)
      const wmInstance = document.querySelector('.watermark')
      if(! wmInstance) {console.log('Watermark is removed!! ')
        document.body.appendChild(watermark)
        return
      }
      if (wmInstance.getAttribute('style') !== styleStr) {
        console.log('Changed the watermark style!! ')
        wmInstance.setAttribute('style', styleStr)
      }
    })
    observer.observe(document.body, {
      childList: true.// Check whether the target child node is added or removed
      attributes: true.// Observe attribute changes
      subtree: true // Observe the descendant node, which defaults to false
    })
  }
  watermark('qwer'.'are you qwer')
</script>
Copy the code

Code words are not easy