JS监听窗口变化和元素变化

resize事件

简介

可用来监听window对象的变化

应用:根据窗口改变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防止多次触发

MutationObserver

简介

  • MutationObserver(callback)为构造函数,可用于实例化监听DOM节点变化的观察器

  • 出自DOM3规范

  • 实例对象拥有三个方法:

    • 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>

需要注意的是:

  • MutationObserver接受的callback执行是异步的,元素更变一般是同步代码,更变后callback会放入消息queue,等待当前一轮事件循环的结束才会执行
  • takeRecords()不是异步的,故可以取到当前在消息queue的元素变化
  • characterData参数只有在元素是textcomment类型时才有效果
参考
原文链接:segmentfault.com

上一篇:Angular笔记——媒体播放
下一篇:实现视频和音频的零延迟是标准的零和博弈

相关推荐

  • 🙋Hanjst汉吉斯特改进+enSafeExpression安全表达式等

    Hanjst汉吉斯特模版语言及模版引擎,近期持续改进升级。 这次改进主要是增加了对安全输出表达式兼容,由于涉及到对软件开发过程中的效率和软件运行效率的平衡和取舍,所以多写了几句,以描述这个权衡利弊对...

    8 天前
  • 🙋Hanjst汉吉斯特升级:+showImageAsync及性能改进等

    自2019年元旦🙋Hanjst汉吉斯特 模板语言及其编译引擎发布,已经过去一年多了。 这期间随着 🙋Hanjst汉吉斯特 的推广应用,我们也陆续发布了如下一些更新内容: 🛠️Hanjst/汉吉...

    1 个月前
  • 😉我用 Nuxt.js 仿了个掘金

    前言 首先肯定是要夸夸掘金啦,最开始从 CSDN 到 博客园 再到 掘金,个人感觉掘金的技术氛围非常的nice,真是个宝藏社区👏。技术文章大多以前端为主,对前端开发者非常友好,质量也是歪瑞古的。

    18 天前
  • 😀一个原生js弹幕库

    danmujs 😀一个原生js弹幕库,基于 CSS3 Animation 地址、核心代码 本项目基于 rcbullets,项目约70%的代码基于rcbullets,首先要感谢这个项目的作者,如...

    4 个月前
  • 🕵️‍♀️由原型到JS中的“模拟类”

    讲述了有关 JavaScript 中原型相关知识,又引出了 JavaScript 中的“类“究竟是什么?,以及一系列相关问题。 一、前置知识 1、JavaScript 的面向对象(OOP) ​ 面向...

    2 个月前
  • 🔥《吊打面试官》系列 Node.js 必知必会必问!

    (/public/upload/f204a3b224d986128f1b4d9b8d06cd17) 前言 codeing 应当是一生的事业,而不仅仅是 30 岁的青春🍚 本文已收录 Git...

    2 个月前
  • 💖CSS + JS 送学妹满屏幕小爱心

    故事开始 午饭时间,暗恋已久的学妹拉着我的衣袖:“学长学长,你能不能让这些爱心变成五颜六色的吗~”。 我在旁边笑开了花~~~ image.png(/public/upload/04aaa24e...

    1 个月前
  • (vuejs学习)2、使用ElementUI(*)

    1.element安装 开发环境是win10,一到node官网下载node的.msi包(https://npm.taobao.org/mirrors/node/v10.16.0/nodev10.16....

    10 个月前
  • (vuejs学习)1、Vue初上手(*)

    参考《官方(https://cli.vuejs.org/zh/guide/installation.html)》官方: Node 版本要求: Vue CLI 需要 Node.js 8.9 或更高...

    10 个月前
  • 黄金搭档 -- JS 装饰器(Decorator)与Node.js路由

    很多面对象语言中都有装饰器(Decorator)函数的概念,Javascript语言的ES7标准中也提及了Decorator,个人认为装饰器是和一样让人兴奋的的变化。

    1 年前

官方社区

扫码加入 JavaScript 社区