JS Monitor Window Change and Element Change

resize incident

brief introduction

Can be used to monitor changes in Windows objects

Application: Change rem according to window

// Datum size
const baseSize = 41.4;
// Setting rem function
function setRem(width) {
  // The current page width scaling ratio relative to 414 width can be modified according to their own needs.
  const scale = width / 414;
  // Set the font size of the page root node
  document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px';
}
window.addEventListener('resize', debounce(setRem));

It should be noted that resize is a high-frequency event, and debounce can be used to prevent multiple triggers.

MutationObserver

brief introduction

  • Mutation Observer (callback) is a constructor that can be used to instantiate observers that monitor DOM node changes
  • From the DOM3 specification
  • Instance objects have three methods:

    • Observation (element, options) starts to observe the nodes and triggers callbacks when changes occur (first placed in the message queue)
    • disconnect() stops the observer until observe() is called again.
    • takeRecords() deletes all pending changes in the message queue and returns

Refer to MDN in detail: MutationObserver

Use

<!DOCTYPE html>
<html>
<head>
    <title>Mutation Observer</title>
    <style type="text/css">
        .box {
            width: 100px;
            height: 100px;
            background-color: red;
        }

        .child{
            width: 50px;
            height: 50px;
            background-color: blue;
        }
    </style>
</head>
<body>
    <div class="box">
        <div class="child"></div>
    </div>

    <script type="text/javascript">
        const { log } = console;

        let MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

        // Callback of box observer
        let boxCallback = (mutationList) => {
            log('box callback is called');
            for (let mutation of mutationList) {
                log(mutation);
                log(mutation.target);
                log('oldValue: ' + mutation.oldValue);
                log('');
            }
        };

        // Callback for text observer
        let textCallback = (mutationList) => {
            log('text callback is called');
            for (let mutation of mutationList) {
                log(mutation);
                log(mutation.target);
                log('oldValue: ' + mutation.oldValue);
                log('');
            }
        };

        // To handle changes received by takeRecords()
        let takeRecordsCallback = (mutationList) => {
            log('take records callback is called');
            for (let mutation of mutationList) {
                log(mutation);
                log(mutation.target);
                log('oldValue: ' + mutation.oldValue);
                log('');
            }
        };

        let observer_box = new MutationObserver(boxCallback); // This callback is asynchronous

        let observer_text = new MutationObserver(textCallback);

        let box = document.querySelector('.box');
        observer_box.observe(box, {
            childList: true,
            attributes: true,
            subtree: true,
            attributeFilter: ['style'],
            attributeOldValue: true // When opened, oldValue records changes, initially null
        });

        box.style.width = '200px'; // MutationRecord {type: "attributes", oldValue: null, ...}
        box.style.width = '400px'; // MutationRecord {type: "attributes", oldValue: "width: 200px;", ...}

        box.appendChild(document.createElement('div')); // MutationRecord {type: "childList", oldValue: null, ...}

        let child = document.querySelector('.child');

        child.style.width = '100px'; // MutationRecord {type: "attributes", oldValue: null, ...}
        child.style.width = '200px'; // MutationRecord {type: "attributes", oldValue: "width: 100px;", ...}

        var mutations = observer_box.takeRecords(); // The above Mutual Record is retrieved. Because the callback is asynchronous, the callback above is not executed.

        if (mutations) {
              takeRecordsCallback(mutations);
        }

        // log('observer_box will disconnect')
        // observer_box.disconnect();

        setTimeout(() => {
            log('observer_box will disconnect')
            observer_box.disconnect();
        }, 0);

        let textNode = document.createTextNode('1');
        child.appendChild(textNode); // MutationRecord {type: "childList", target: div.child, ...}

        // characterData needs to be used in text or comment elements to be effective
        observer_text.observe(textNode, {
            characterData: true,
            characterDataOldValue: true // oldValue is initially the value of text
        });

        textNode.appendData('2'); // MutationRecord {type: "characterData", target: text, oldValue: "1"}
        textNode.appendData('3'); // MutationRecord {type: "characterData", target: text, oldValue: "12"}

    </script>
</body>
</html>

It should be noted that:

  • Callback execution accepted by Mutation Observer is asynchronous. Element changes are usually synchronous code. After changes, callback will be put into message queue, waiting for the end of the current round of event cycle to execute.
  • takeRecords() is not asynchronous, so you can retrieve the current element change in the message queue
  • characterData parameters are valid only if the element is text or comment type

Reference resources

Tags: Javascript Windows

Posted on Sat, 12 Oct 2019 14:14:49 -0700 by byenary