乐趣区

关于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);
 }

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

退出移动版