关于javascript:今天我使用了MutationObserver

什么是MutationObserver

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

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

用户更加关注后续的业务,上述这些性能只是辅助性能,这个我的项目的首次版本中,我将所有的性能都写在了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);
 }

这样,我就不必放心当其余单例笼罩已有单例时,被笼罩的单例不会革除实例的问题了。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理