今天,我使用了MutationObserver

时间:2020-7-28 作者:admin

什么是MutationObserver

MutationObserver接口提供了监视对DOM树所做更改的能力。它被设计为旧的Mutation Events功能的替代品,该功能是DOM3 Events规范的一部分。

其实就是当指定的DOM发生变化时,我们使用MutationObserver定义的方法会被执行。
如果你还没有get到点的话,不用急,下面介绍个实例。
有时候,当我们的功能都是一些弹框类的样式,不会经常出现时,
比如账号登陆,手机登陆,重置密码,绑定手机号等等。

今天,我使用了MutationObserver


用户更加关注后续的业务,上述这些功能只是辅助功能,这个项目的初次版本中,我将所有的功能都写在了index.html中默认隐藏,大概的结构就是:

<div class = "loginPage"></div>
<div class = "phoneLoginPage"></div>
<div class = "resetpwdPage"></div>
<div class = "bindphonePage"></div>

然后在使用的时候显示出来。
这样写功能实现上没什么问题,也很好理解,
但是后续优化的时候发现,功能堆积到一定程度,造成index.html非常的臃肿,代码里面对于图片的引用都会造成首次加载时,非常多的http请求。

自然而然我想到的解决方案 是将单个的功能都模块化,当需要时往页面中添加。我在index.html中添加一个容器,专门放上面这些功能。

<div class = "contont-div"></div>

然后每个功能一个js脚本,做成单例,当需要的时候show出来,不需要的时候hide

(function (g) {
    g.SinglePage.loginPage = (function () {
        var _$reg = null;
        return {
            show: function () {
                if (_$reg) {
                    return;
                }
                _$reg = ......
                //下面是show的具体业务逻辑省略
            },
            hide: function () {
                if (_$reg) {
                    _$reg.remove();
                }
                _$reg = null;
            }
        }
    })();
}(window))

最开始的时候,一切都很顺利,当需要登录的时候,我打开登陆,然后在其他面板打开时候关闭登陆框,但是随着功能越来越多,出现了一个问题,我不确定我打开的面板什么时候会被关闭了。

$('.contont-div').html();

因为用的是jq的html方法往容器中添加html代码,显示上不会有什么问题,但是,当我不知道我打开的面板什么时候关闭时,我就没法让单例销毁,造成的后果就是不是我手动关闭的单例,再也打不开了,因为,单例的实例没有被销毁。

因此使用了MutationObserver。
为了避免我们在监测到dom发生变化时,用switch case 去找对应的单例的实例,我们改造一下功能的html

//登陆功能
<div class = "mul_loginPage"></div>

其中mul_后面的字符串和登陆功能的脚本名称保持一致。
每个单例代码中都包含hide方法,用于清除实例。
其他功能同理。

let targetNode = document.querySelector(`.contont-div`);
 let config = {
     childList: true
 };
 const mutationCallback = (mutations) => {
     for (let mutation of mutations) {
         let type = mutation.type;
         switch (type) {
             case "childList":
                 let _removeNodes = mutation.removedNodes;
                 for (let i = 0, l = _removeNodes.length; i < l; i++) {
                     let _tmpNode = _removeNodes[i];
                     let _class = $(_tmpNode).attr('class');
                     if (!_class) {
                         continue;
                     }
                     let _arg = _class.split('_');
                     var _sj = _arg[1];
                     if (_sj && g.SinglePage[_sj]) {
                         g.SinglePage[_sj].hide();
                     }
                 }
                 break;
         }
     }
 };
 let observer = new MutationObserver(mutationCallback);
 if (targetNode) {
     observer.observe(targetNode, config);
 }

这样,我就不用担心当其他单例覆盖已有单例时,被覆盖的单例不会清除实例的问题了。

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。