共计 1872 个字符,预计需要花费 5 分钟才能阅读完成。
什么是 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);
}
这样,我就不必放心当其余单例笼罩已有单例时,被笼罩的单例不会革除实例的问题了。