这是特地探究 JavaScript 及其所构建的组件的系列文章的第10篇。
想浏览更多优良文章请猛戳GitHub博客,一年百来篇优良文章等着你!
假如你错过了前面的章节,能够在这里找到它们:
- JavaScript 是怎样事情的:引擎,运转时和挪用客栈的概述!
- JavaScript 是怎样事情的:深切V8引擎&编写优化代码的5个技能!
- JavaScript 是怎样事情的:内存治理+怎样处置惩罚4个罕见的内存走漏 !
- JavaScript 是怎样事情的:事宜轮回和异步编程的兴起+ 5种运用 async/await 更好地编码体式格局!
- JavaScript 是怎样事情的:深切探究 websocket 和HTTP/2与SSE +怎样挑选准确的途径!
- JavaScript 是怎样事情的:与 WebAssembly比较 及其运用场景 !
- JavaScript 是怎样事情的:Web Workers的构建块+ 5个运用他们的场景!
- JavaScript 是怎样事情的:Service Worker 的生命周期及运用场景!
- JavaScript 是怎样事情的:Web 推送关照的机制!
Web 应用顺序在客户端变得越来越重,缘由很多,比方须要更雄厚的 UI 来包容更庞杂的应用顺序供应的内容,及时盘算等等。庞杂性的增添使得在 Web 应用顺序生命周期的每一个给定时刻都很难晓得 UI 的确实状况。
而当你在搭建某些框架或许库的时刻,甚至会越发难题,比方,前者须要依据 DOM 来作出反应并实行特定的行动。
概述
Mutation Observer API 用来看管 DOM 变动。DOM 的任何变动,比方节点的增减、属性的变动、文本内容的变动,这个 API 都能够获得关照。
概念上,它很靠近事宜,能够理解为 DOM 发作变动就会触发 Mutation Observer 事宜。然则,它与事宜有一个实质差别:事宜是同步触发,也就是说,DOM 的变动立时会触发响应的事宜;Mutation Observer 则是异步触发,DOM 的变动并不会立时触发,而是要比及当前一切 DOM 操纵都完毕才触发。
如许设想是为了敷衍 DOM 变动频仍的特性。举例来说,假如文档中一连插进去1000个 <li>
元素,就会一连触发1000个插进去事宜,实行每一个事宜的回调函数,这极能够形成浏览器的卡顿;而 Mutation Observer 完整差别,只在 1000
个段落都插进去完毕后才会触发,而且只触发一次。
Mutation Observer有以下特性:
- 它守候一切剧本使命完成后,才会运转,即采纳异步体式格局
- 它把 DOM 变动纪录封装成一个数组举行处置惩罚,而不是一条条地一般处置惩罚 DOM 变动
- 它即能够视察发作在 DOM 节点的一切变动,也能够视察某一类变动
为何要要监听 DOM?
在很多状况下,MutationObserver API 都能够派上用场。比方:
- 你愿望关照 Web 应用顺序访问者,他当前地点的页面发作了一些变动。
- 你正在开辟一个新的 JavaScript 框架,须要依据 DOM 的变化动态加载 JavaScript 模块。
- 或许你正在开辟一个所见即所得(WYSIWYG) 编辑器,试图完成取消/重做功用。经由过程应用 MutationObserver API,你能够晓得在任何给定的点上举行了哪些变动,因而能够轻松地取消这些变动。
这些只是 MutationObserver 能够供应协助的几个例子。
MutationObserver 用法
在应用顺序中完成 MutationObserver 相称简朴。你须要经由过程传入一个函数来建立一个 MutationObserver 实例,每当有变化发作,这个函数将会被挪用。函数的第一个参数是变动数组,每一个变化都邑供应它的范例和已发作的变化的信息。
var mutationObserver = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation);
});
});
这个被建立的对象有三个要领:
- observe — 启动监听
- disconnect — 用来住手视察
- takeRecords — 返用来消灭变动纪录,即不再处置惩罚未处置惩罚的变动。
observe()
observe 要领用来启动监听,它接收两个参数。
- 第一个参数:所要视察的 DOM 节点
- 第二个参数:一个设置对象,指定所要视察的特定变
下面的片断展现了怎样最先启动监听(observe ):
// 最先侦听页面的根 HTML 元素中的变动。
mutationObserver.observe(document.documentElement, {
attributes: true,
characterData: true,
childList: true,
subtree: true,
attributeOldValue: true,
characterDataOldValue: true
});
如今,假定 DOM 中有一些异常简朴的 div:
<div id="sample-div" class="test"> Simple div </div>
运用 JQuery 来移除这个 div 上的 class:
$("#sample-div").removeAttr("class");
正如我们已最先视察到的,在挪用 mutationObserver.observe(…)
以后,将在掌握台中看到响应 MutationRecord 的日记:
这个是由移除 class
属性致使的变化。
MutationRecord
对象包含了DOM的相干信息,有以下属性:
type:视察的变动范例(attribute、characterData或许childList)
target:发作变动的 DOM 节点
addedNodes:新增的 DOM 节点
removedNodes:删除的 DOM 节点
previousSibling:前一个同级节点,假如没有则返回 null
nextSibling:下一个同级节点,假如没有则返回 null
attributeName:发作变动的属性。假如设置了attributeFilter,则只返回预先指定的属性。
oldValue:变动前的值。这个属性只对 attribute 和 characterData 变动有效,假如发作 childList 变动,则返回 null
末了,为了在使命完成后住手视察 DOM,能够实行以下操纵:
mutationObserver.disconnect();
如今,MutationObserver
已被普遍支撑:
备择计划
MutationObserver 在之前还没有的,那末在 MutationObserver 还没涌现之前,开辟者采纳什么计划呢?
这是几个可用的其他选项:
- 轮询(Polling)
- MutationEvents
- CSS animations
轮询(Polling)
最简朴和最简朴的要领是轮询。运用浏览器 setInterval
要领,能够设置一个使命,按期搜检是不是发作了任何变动。固然,这类要领会明显下降web 应用顺序/网站的机能。
MutationEvents
在2000年,MutationEvents API 被引入。虽然很有效,但在 DOM中 的每一次变动都邑触发转变事宜,这同样会致使机能题目。如今 MutationEvents API 已被弃用,很快当代浏览器将完整住手支撑它。
CSS animations
另一个有点新鲜的挑选是依靠 CSS 动画。这听起来能够有点令人困惑。基本上,我们的主意是建立一个动画,一旦元素被增加到 DOM 中,动画就会被触发。动画最先的那一刻,animationstart
事宜将被触发:假如已将事宜处置惩罚顺序附加到该事宜,那末你将确实地晓得元素什么时候被增加到 DOM 中。动画的实行时候周期应当很小,用户险些看不到它。
起首,须要一个父级元素,我们在它的内部监听节点的插进去:
<div id=”container-element”></div>
为了获得节点插进去的处置惩罚器,须要设置一系列的 keyframe 动画,当节点插进去的时刻,动画将会最先。
@keyframes nodeInserted {
from { opacity: 0.99; }
to { opacity: 1; }
}
建立 keyfram
后,还须要把它放入你想监听的元素上,注重应设置很小的 duration 值 —— 它们将会削弱动画在浏览器上留下的陈迹。
#container-element * {
animation-duration: 0.001s;
animation-name: nodeInserted;
}
这会将动画增加到 container-element
的一切子节点。 动画完毕时,将触发插进去事宜。
我们须要一个 JavaScript 函数作为事宜监听器。在函数中,必需举行初始的 event.animationName
搜检以确保它是我们想要的动画。
var insertionListener = function(event) {
// Making sure that this is the animation we want.
if (event.animationName === "nodeInserted") {
console.log("Node has been inserted: " + event.target);
}
}
如今是时刻为父级元素增加事宜监听了:
document.addEventListener(“animationstart”, insertionListener, false); // standard + firefox
document.addEventListener(“MSAnimationStart”, insertionListener, false); // IE
document.addEventListener(“webkitAnimationStart”, insertionListener, false); // Chrome + Safari
浏览器对CSS动画的支撑状况:
MutationObserver 比上述处理计划有很多长处。实质上,它涵盖了 DOM 中能够发作的每一个变动,并且在批量触发变动时,它的优化水平更高。最重要的是,一切重要的当代浏览器都支撑 MutationObserver,另有一些运用引擎下 MutationEvents 的 polyfill。
原文:
https://blog.sessionstack.com…
代码布置后能够存在的BUG没法及时晓得,预先为了处理这些BUG,花了大批的时候举行log 调试,这边顺便给人人引荐一个好用的BUG监控东西 Fundebug。
你的点赞是我延续分享好东西的动力,迎接点赞!