DOM MutationObserver,在不影响浏览器性能的情况下响应DOM更改。
Dom Mutation Events 在提出时的确是一个很不错的想法, 随着web页面的动态性不断增强,web开发者非常欢迎这种能够侦听DOM中的更改并对其作出反应的事件,然而在实践中,DOM Mutation Events存在着严重的性能和稳定性问题,所以此方法已被弃用多年。
然而,DOM Mutation Events 最初的想法还是很有吸引力,因此,在2011年9月,一组谷歌和Mozilla工程师宣布了一项新提议,即DOM MutationObserver,该提议将提供性能改进后的类似功能。这个新的DOM Api可以在Firefox和Webkit以及Chrome 18中轻松构建。
简单来说,MutationObserver实现是这样的:
// select the target node
var target = document.querySelector('#some-id');
// create an observer instance
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation.type);
});
});
// configuration of the observer:
var config = { attributes: true, childList: true, characterData: true }
// pass in the target node, as well as the observer options
observer.observe(target, config);
// later, you can stop observing
observer.disconnect();
复制代码
和已废弃的DOM Mutation Events规范相比,这个新规范的主要优点在于效率,如果您正在观察一个节点进行更改,则在DOM完成更改之前触发回调,当回调被触发时,它将提供对DOM的更改列表,然后您可以循环该列表并选择对其作出响应。
这还意味着,您编写的任何代码都需要处理观察者结果,以便对您正在寻找的更改做出反应。下面是一个紧凑的观察者的例子,它监听可编辑有序列表中的变化:
<!DOCTYPE html>
<ol contenteditable oninput="">
<li>Press enter</li>
</ol>
<script>
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
var list = document.querySelector('ol');
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.type === 'childList') {
var list_values = [].slice.call(list.children)
.map( function(node) { return node.innerHTML; })
.filter( function(s) {
if (s === '<br />') {
return false;
}
else {
return true;
}
});
console.log(list_values);
}
});
});
observer.observe(list, {
attributes: true,
childList: true,
characterData: true
});
</script>
复制代码
如果你运行这个示例,你会发现一个奇怪之处,它将在每个li中按enter键时触发回调,用户操作导致从DOM添加或删除节点时触发回调。这是与其他技术(如将事件绑定到按键或更常见的事件(如“click”)的重要区别。mutationobserver的工作方式与这些技术不同,因为它们是由DOM本身的更改触发的,而不是由通过JS或用户交互生成的事件触发的。
这些有什么用呢?
我不认为大多数JS黑客会马上在他们的代码中添加mutation observers。这个新api的最大受众可能是那些编写JS框架的人,他们主要是为了解决问题和创建以前无法完成的交互,或者至少没有合理的性能。另一个用例是这样一种情况:您正在使用框架来操作DOM,并且需要对这些修改做出有效的反应(而且没有setTimeout攻击!) Dom Mutation Events api的另一个常见用法是在浏览器扩展中。
原文地址:DOM MutationObserver – reacting to DOM changes without killing browser performance.