JS監聽窗口變化和元素變化

resize事件

簡介

可用來監聽window對象的變化javascript

應用:根據窗口改變rem

// 基準大小
const baseSize = 41.4;
// 設置 rem 函數
function setRem(width) {
  // 當前頁面寬度相對於 414 寬的縮放比例,可根據本身須要修改。
  const scale = width / 414;
  // 設置頁面根節點字體大小
  document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px';
}
window.addEventListener('resize', debounce(setRem));

須要注意的是resize是高頻事件,可以使用debounce防止屢次觸發css

MutationObserver

簡介

  • MutationObserver(callback)爲構造函數,可用於實例化監聽DOM節點變化的觀察器
  • 出自DOM3規範
  • 實例對象擁有三個方法:html

    • observe(element, options)開始觀察節點,發生變化時觸發回調(先放到消息隊列裏
    • disconnect()中止觀察器,直到再次調用observe()
    • takeRecords()將消息隊列裏未處理的變化通知所有刪除並返回
詳細參考MDN: MutationObserver

使用

<!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;

        // box觀察器的回調
        let boxCallback = (mutationList) => {
            log('box callback is called');
            for (let mutation of mutationList) {
                log(mutation);
                log(mutation.target);
                log('oldValue: ' + mutation.oldValue);
                log('');
            }
        };

        // 用於text觀察器的回調
        let textCallback = (mutationList) => {
            log('text callback is called');
            for (let mutation of mutationList) {
                log(mutation);
                log(mutation.target);
                log('oldValue: ' + mutation.oldValue);
                log('');
            }
        };

        // 用於處理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); // 此回調是異步的

        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 // 開啓後oldValue會記錄變化,初始爲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(); // 將上面的MutationRecord都獲取了,因爲callback都是異步的,故上面的的callback未執行

        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須要用在text或comment元素纔有效果
        observer_text.observe(textNode, {
            characterData: true,
            characterDataOldValue: true // oldValue初始爲text的值
        });

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

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

須要注意的是:java

  • MutationObserver接受的callback執行是異步的,元素更變通常是同步代碼,更變後callback會放入消息queue,等待當前一輪事件循環的結束纔會執行
  • takeRecords()不是異步的,故能夠取到當前在消息queue的元素變化
  • characterData參數只有在元素是textcomment類型時纔有效果

參考

相關文章
相關標籤/搜索