前言
在MVVM框架中,一是监听数据变化,数据驱动。
- 我们都知道通过Object.defineProperties(),来监听数据的变化,或者使用,代理和反射。
- 其实在MVVM中,也有操作DOM的场景。那么,我们是通过哪些API来监听DOM的变化的呢?
当我们,通过JS操作了DOM之后,我们需要通知到DOM来更新视图。在VUE中,是维护了一个异步的队列。并不是你修改了DOM就会直接更新到视图上面。
监听DOM变化的方法:
- 轮询
- MutationEvents(基本已废弃)
- CSS 动画
以上三种都不是很好的方法。那么,我们今天来介绍一下,现在比较常用的:
- MutationObserver
我们选择Mutation Observer
概述
Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。 Mutation Observer 则是异步触发,DOM 的变动并不会马上触发,而是要等到当前所有 DOM 操作都结束才触发。 这样设计是为了应付 DOM变动频繁的特点。
举例来说,如果文档中连续插入1000个li元素,就会连续触发1000个插入事件,执行每个事件的回调函数,这很可能造成浏览器的卡顿;而 Mutation Observer 完全不同,只在 1000 个段落都插入结束后才会触发,而且只触发一次。
Mutation Observer有以下特点:
- 等待所有脚本任务完成后,才会运行,即采用异步方式
- 把 DOM 变动记录封装成一个数组进行处理,而不是一条条地个别处理 DOM 变动
- 即可以观察发生在 DOM 节点的所有变动,也可以观察某一类变动
使用
var observe = new MutationObserver(function(mutations, observer){
});
var el = document.querySelector('#app');
var options = {
'childList': true,
'attributes':true
} ;
observer.observe(el, options);
// 创建并返回一个 MutationObserver 实例, 并侦听el元素的变动。
小例子
MutationObserver的callback回调函数是异步的,只有在全部DOM操作完成之后才会调用callback。
<div id='target' class='block' name='target'>
target的第一个子节点
<p>
<span>target的后代</span>
</p>
</div>
var target=document.getElementById('target');
var i=0
var observe=new MutationObserver(function (mutations,observe) {
i++
});
observe.observe(target,{ childList: true});
target.appendChild(docuemnt.createTextNode('1'));
target.appendChild(docuemnt.createTextNode('2'));
target.appendChild(docuemnt.createTextNode('3'));
console.log(i) //1 callback的回调次数
应用
在很多情况下,MutationObserver API 都可以派上用场。例如:
- 你希望通知 Web 应用程序访问者,他当前所在的页面发生了一些更改。
- 你正在开发一个新的 JavaScript 框架,需要根据 DOM 的变化动态加载 JavaScript 模块。
兼容性
看评论中,对兼容性比较关注,特贴出来。也可去mdn直接查看
总结
- MutationObserver接口提供了监视对DOM树所做更改的能力。它被设计为旧的Mutation Events功能的替代品,该功能是DOM3 Events规范的一部分。(MDN)
- DOM MutationObserver,在不影响浏览器性能的情况下响应DOM更改
- 等待所有脚本任务完成后,才会运行,即采用异步方式