MutationObserver监视对DOM 树所做更改的功能妙用
作者:收破烂的来了
前言
上一篇给大家讲解了关于IntersectionObserver的使用。 这一篇给大家讲解一下MutationObserver的使用。
使用场景
首先关于MutationObserver的作用就是监视对DOM所做更改的能力,那么他的使用面就特别的广泛了,比如组件的自适应,垃圾回收,还有就是在不支持prmose的场景下实现异步完成函数,防止用户用devtools工具修改一些样式,如:通过修改css或删除标签去除图片水印等。
当然只要是设计到DOM变动的MutationObserver都能帮你一些忙。
书写格式
老规矩还是先放链接MutationObserver - Web API 接口参考 | MDN (mozilla.org)
首先MutationObserver同样也是监听一个Node节点,然后通过相关的配置项 设置监听的范围,当范围内的相关属性发生变化,便会触发MutationObserver的回调函数。
var observer = new MutationObserver(callback);
相关方法
observe
mutationObserver.observe(target[, options])
target即我们要监听的Node节点,options即为配置项。
options属性有以下几个(我写的简短一点,详细请点击链接看文档):
- subtree : true, ----将会监听以 target为根节点的整个子树。包括子树中所有节点的属性,而不仅仅是针对target。
- childList: true, ----监听 target 节点中发生的节点的新增与删除(同时,如果 subtree 为 true,会针对整个子树生效)。
- attributes : true,----观察所有监听的节点属性值的变化。默认值为 true,当声明了 attributeFilter或 attributeOldValue,默认 值则为 false。
- characterData : true,----监听声明的target 节点上所有字符的变化,如果声明了characterDataOldValue,默认值则为 false
- attributeOldValue : true,---记录上一次被监听的节点的属性变化。
- characterDataOldValue : true----当为 true 时,记录前一个被监听的节点中发生的文本变化。
disconnect()
mutationObserver.disconnect()
disconnect方法告诉观察者停止观察变动。可以通过调用其 observe() 方法来重用观察者。()意思就是停止监听)
takeRecords
mutationRecords = mutationObserver.takeRecords()
takeRecords方法返回已检测到但尚未由观察者的回调函数处理的所有匹配 DOM 更改的列表,使变更队列保持为空。此方法最常见的使用场景是在断开观察者之前立即获取所有未处理的更改记录,以便在停止观察者时可以处理任何未处理的更改。
MutationRecord对象
DOM每次发生变化,就会生成一条变动记录(MutationRecord实例)。该实例包含了与变动相关的所有信息。MutationObserver处理的就是一个个MutationRecord实例组成的数组。
MutationRecord包含了Dom的有关信息,有以下属性:
- type:观察变动的类型,即原因(attribute、characterData或者childList等)
- target : 发生变动的DOM节点
- addedNodes :返回新增的DOM节点,如果没有则为空(null)。
- removedNodes : 返回删除的DOM节点,如果没有则为空(null)。
- previousSibling :返回被添加或移除的节点之前的兄弟节点,或者 null。即上一个兄弟节点
- nextSibling : 返回被添加或移除的节点之后的兄弟节点,或者 null。即下一个兄弟节点
- attributeName:返回被修改的属性的属性名,或者 null。
- oldValue:这个属性只对attribute和characterData变动生效,如果发生childList变动,则返回null。
案例
一、
去除水印的操作(这里只讲下原理、概念),原理就是通过监听节点的属性和后代节点和属性,来实现无法去除的效果,简单案例
// 选择需要观察变动的节点 const ul = document.querySelector('ul'); // 观察器的配置(需要观察什么变动) const config = { 'childList': true, 'subtree': true ,'attributes':true}; // 当观察到变动时执行的回调函数 const callback = function(mutationsList, observer) { console.log(111); console.log(mutationsList,observer); }; // 创建一个观察器实例并传入回调函数 const observer = new MutationObserver(callback); // 以上述配置开始观察目标节点 observer.observe(ul, config); const btn =document.querySelector('button') console.log(li); btn.addEventListener('click',()=>{ ul.style.background='pink' }) // // 之后,可停止观察 // observer.disconnect();
无论我通过控制台去删除 ul中的li(子代)标签还是改变ul的相关属性或li(子代)的属性 或者添加li操作。MutationObserver根据配置项监听,触发回调函数。这也就是为什么通过一些方法想去去除水印。会发现删不掉的原因。
注:style样式只有内联样式才可以触发。CSS选择器是无法触发的。
操作相关触发结果:
二、
如面试题:异步完成一个函数,并尽量将任务放在微任务中。 异步完成函数的原理,因为MutationObserver实例的callback回调函数与IntersectionObserver一样都为异步,这是W3C规定的。而且回调函数为微任务。
此处characterData:true,对应的就是节点字符发生变化。
function asyncRun(fun){ //如果浏览器支持promise if(typeof Promise !=='undefined'){ Promise.resolve().then(fun); //如果浏览器支持 MutationObserve }else if(typeof MutationObserver!== 'undefined'){ const observe =new MutationObserver(fun); const textNode=document.createTextNode('0'); observe.observe(textNode,{characterData:true,}); textNode.data='1' //都不支持则放入定时器 }else{ setTimeout(fun) } }
三、
在vue的nextTick源码中也用到了MutationObserver来实现异步调度机制,同上面的面试题类似。
总结
在我们日常开发中,可以用到MutationObserver的地方是特别特别多的。这是一个必会的技巧,我这里只是写了一些基础用法,大家还是要多看文档多用才能够灵活运用。
切记多看文档!!!
再放一遍链接,MutationObserver - Web API 接口参考 | MDN (mozilla.org)
以上就是MutationObserver监视对DOM 树所做更改的功能妙用的详细内容,更多关于MutationObserver监视DOM 树更改的资料请关注脚本之家其它相关文章!