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);
}
这样,我就不用担心当其他单例覆盖已有单例时,被覆盖的单例不会清除实例的问题了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。