当前位置:网站首页>MutationObserver文档学习
MutationObserver文档学习
2022-07-29 06:04:00 【浮桥】
1. 概述
Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。
概念上,它很接近事件,可以理解为 DOM 发生变动就会触发 Mutation Observer 事件。但是,它与事件有一个本质不同:事件是同步触发,也就是说,DOM 的变动立刻会触发相应的事件;Mutation Observer 则是异步触发,DOM 的变动并不会马上触发,而是要等到当前所有 DOM 操作都结束才触发。
这样设计是为了应付 DOM 变动频繁的特点。举例来说,如果文档中连续插入1000个
元素,就会连续触发1000个插入事件,执行每个事件的回调函数,这很可能造成浏览器的卡顿;而 Mutation Observer 完全不同,只在1000个段落都插入结束后才会触发,而且只触发一次。
Mutation Observer 有以下特点:
- 它等待所有脚本任务完成后,才会运行(即异步触发方式)。
- 它把 DOM 变动记录封装成一个数组进行处理,而不是一条条个别处理 DOM 变动。
- 它既可以观察 DOM 的所有类型变动,也可以指定只观察某一类变动。
2. MutationObserver 构造函数
使用时,首先使用MutationObserver构造函数,新建一个观察器实例,同时指定这个实例的回调函数。回调函数,会在每次 DOM 变动后调用。该回调函数接受两个参数,第一个是变动数组,第二个是观察器实例
var observer = new MutationObserver(function (mutations, observer) {
mutations.forEach(function(mutation) {
console.log(mutation);
});
});
3. MutationObserver 的实例方法
1. observe()
observe方法用来启动监听,它接受两个参数。第一个是所要观察的DOM元素是article,第二个是所要观察的变动类型(子节点变动和属性变动)。
第一个参数:所要观察的 DOM 节点
第二个参数:一个配置对象,指定所要观察的特定变动
var article = document.querySelector('article');
var options = {
'childList': true,
'attributes':true
} ;
observer.observe(article, options);
(1)观察器所能观察的 DOM 变动类型(即上面代码的options对象),有:
childList:子节点的变动(指新增,删除或者更改)。
attributes:属性的变动。
characterData:节点内容或节点文本的变动。
想要观察哪一种变动类型,就在option对象中指定它的值为true。需要注意的是,必须同时指定childList、attributes和characterData中的一种或多种,若未均指定将报错。
(2)除了变动类型,options对象还可以设定以下属性:
subtree:布尔值,表示是否将该观察器应用于该节点的所有后代节点。
attributeOldValue:布尔值,表示观察attributes变动时,是否需要记录变动前的属性值。
characterDataOldValue:布尔值,表示观察characterData变动时,是否需要记录变动前的值。
attributeFilter:数组,表示需要观察的特定属性(比如[‘class’,‘src’])。
// 开始监听文档根节点(即<html>标签)的变动
mutationObserver.observe(document.documentElement, {
attributes: true,
characterData: true,
childList: true,
subtree: true,
attributeOldValue: true,
characterDataOldValue: true
});
对一个节点添加观察器,就像使用addEventListener方法一样,多次添加同一个观察器是无效的,回调函数依然只会触发一次。但是,如果指定不同的options对象,就会被当作两个不同的观察器。
2. disconnect(),takeRecords()
(1) disconnect方法用来停止观察。调用该方法后,DOM 再发生变动,也不会触发观察器。
observer.disconnect();
(2) takeRecords方法用来清除变动记录,即不再处理未处理的变动。该方法返回变动记录的数组。
observer.takeRecords();
4. MutationRecord 对象
DOM 每次发生变化,就会生成一条变动记录(MutationRecord 实例)。该实例包含了与变动相关的所有信息。Mutation Observer 处理的就是一个个MutationRecord实例所组成的数组。
MutationRecord对象包含了DOM的相关信息,有如下属性:
type:观察的变动类型(attribute、characterData或者childList)。
target:发生变动的DOM节点。
addedNodes:新增的DOM节点。
removedNodes:删除的DOM节点。
previousSibling:前一个同级节点,如果没有则返回null。
nextSibling:下一个同级节点,如果没有则返回null。
attributeName:发生变动的属性。如果设置了attributeFilter,则只返回预先指定的属性。
oldValue:变动前的值。这个属性只对attribute和characterData变动有效,如果发生childList变动,则返回null。
5. 应用示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MutationObserver 构造函数</title>
<style> ul {
width: 510px; padding: 10px; border: 1px solid #ccc; } li {
width: 500px; height: 60px; list-style-type: none; line-height: 60px; margin-bottom: 10px; font-size: 36px; color: #535353; border: 1px solid rgb(245, 156, 156); } </style>
</head>
<body>
<div>
<button onclick="stopObserving()">停止观察</button>
</div>
<ul class="article1">
<li class="list1">1</li>
<li class="list1">2</li>
<li class="list1">3</li>
</ul>
<div>
<button onclick="childChange()">子元素的变动</button>
<button onclick="openObserving(1)">开启观察</button>
</div>
<ul class="article2">
<li class="list2">1</li>
<li class="list2">2</li>
<li class="list2">3</li>
</ul>
<div>
<button onclick="propertiesChange()">属性的变动</button>
<button onclick="openObserving(2)">开启观察</button>
</div>
<script type="text/javaScript"> var article = document.querySelector(".article1") var article2 = document.querySelector(".article2") var timer = null function childChange(){
console.log('子元素的变动') var lis = document.getElementsByClassName('list1') if(!lis.length){
for(let i=0;i<6;i++){
timer = setTimeout(() => {
var li = document.createElement('li'); li.innerHTML = i + 1 article.appendChild(li); }, 1000*(i+1)); } }else{
for(let i=0;i<lis.length;i++){
timer = setTimeout(() => {
console.log('变动下标:',i) article.removeChild(lis[0]) }, 1000*(i+1)); } } // var li1 = lis[0] // // 删除第一个子节点 // ul.removeChild(li1) } function propertiesChange(){
console.log('属性的变动') // clientWidth:获取元素可视部分的宽度,即 CSS 的 width 和 padding 属性值之和,元素边框和滚动条不包括在内,也不包含任何可能的滚动区域 // console.log(article2.clientWidth); if(article2.clientWidth === 530){
article2.style.width = '700px' }else{
article2.style.width = '510px' } } /** 1. MutationObserver 构造函数使用 * 使用MutationObserver构造函数,新建一个观察器实例,同时指定这个实例的回调函数。 * 回调函数,会在每次 DOM 变动后调用。该回调函数接受两个参数,第一个是变动数组,第二个是观察器实例。 */ var callback = function (mutations, observer) {
console.log('监听',mutations, observer) mutations.map(function(record){
// 子元素的变动 console.log('Mutation type: ' + record.type); console.log('Mutation target: ' + record.target); // 属性的变动 console.log('Previous attribute value: ' + record.oldValue); /** 变动记录: MutationRecord对象(及mutations对象) * DOM 每次发生变化,就会生成一条变动记录(MutationRecord 实例)。该实例包含了与变动相关的所有信息。Mutation Observer 处理的就是一个个MutationRecord实例所组成的数组。 * * MutationRecord对象包含的DOM的相关信息: * (1). type:观察的变动类型(attribute、characterData或者childList)。 * (2). target:发生变动的DOM节点。 * (3). addedNodes:新增的DOM节点。 * (4). removedNodes:删除的DOM节点。 * (5). previousSibling:前一个同级节点,如果没有则返回null。 * (6). nextSibling:下一个同级节点,如果没有则返回null。 * (7). attributeName:发生变动的属性。如果设置了attributeFilter,则只返回预先指定的属性。 * (8). oldValue:变动前的值。这个属性只对attribute和characterData变动有效,如果发生childList变动,则返回null。 */ }); } var observer = new MutationObserver(callback) /** 2. MutationObserver 的实例方法 * observe方法用来启动监听,它接受两个参数。(第一个参数:所要观察的 DOM 节点,第二个参数:一个配置对象,指定所要观察的特定变动) * * 配置对象: * (1) childList:子节点的变动(指新增,删除或者更改)。 * (2) attributes:属性的变动。 * (3) characterData:节点内容或节点文本的变动。 * (4) subtree:布尔值,表示是否将该观察器应用于该节点的所有后代节点。 * (5) attributeOldValue:布尔值,表示观察attributes变动时,是否需要记录变动前的属性值。 * (6) characterDataOldValue:布尔值,表示观察characterData变动时,是否需要记录变动前的值。 * (7) attributeFilter:数组,表示需要观察的特定属性(比如['class','src'])。 */ // 注: 必须同时指定childList、attributes和characterData中的一种或多种,若未均指定将报错。 // console.log("article", article,article2) // 子元素的变动配置 var options = {
'attributes': true, 'childList': true, 'subtree': true } // 属性的变动配置 var options2 = {
'attributes': true, 'attributeOldValue': true, } observer.observe(article, options) observer.observe(article2, options2) function stopObserving(params) {
/** disconnect(): * disconnect方法用来停止观察。调用该方法后,DOM 再发生变动,也不会触发观察器。 */ console.log('停止观察') observer.disconnect(); /** takeRecords(): * takeRecords方法用来清除变动记录,即不再处理未处理的变动。该方法返回变动记录的数组。 */ // 保存所有没有被观察器处理的变动 var changes = observer.takeRecords(); console.log('没有被观察器处理的变动',changes) } function openObserving(params) {
if(params===1){
console.log('开启子元素的变动的观察') observer.observe(article, options) }else{
console.log('开启属性的变动观察') observer.observe(article2, options2) } } </script>
</body>
</html>


- 执行结果可以看出
disconnect()方法会停止所有的观察,执行后需要观察的元素需要从新开启观察
边栏推荐
- Unity免费元素特效推荐
- Teacher wangshuyao's notes on operations research 04 fundamentals of linear algebra
- Not so simple singleton mode
- Pytorch多GPU条件下DDP集群分布训练实现(简述-从无到有)
- Federal learning backdoor attack summary (2019-2022)
- 【论文阅读 | 冷冻电镜】RELION 4.0 中新的 subtomogram averaging 方法解读
- MySQL:当你CRUD时BufferPool中发生了什么?十张图就能说清楚
- Security in quantum machine learning
- Flink实时仓库-DWD层(下单-多张表实现join操作)模板代码
- SSH免密登录-两台虚拟机建立免密通道 双向信任
猜你喜欢

CVPR2022Oral专题系列(一):低光增强

Teacher wangshuyao's notes on operations research 04 fundamentals of linear algebra

MySQL: what happens in the bufferpool when you crud? Ten pictures can make it clear

IDEA找不到Database解决方法

Unity exploration plot access design analysis & process + code specific implementation

Teacher Wu Enda's machine learning course notes 02 univariate linear regression

C language memory stack and heap usage

Sword finger offer II 115: reconstruction sequence

SDN topology discovery principle

leetcode-592:分数加减运算
随机推荐
Overview of database system
Teacher Cui Xueting's course notes on optimization theory and methods 00 are written in the front
Excerpts from good essays
IO流 - File - properties
Decompilation of wechat applet
The latest pycharm2018 cracking tutorial
新同事写了几段小代码,把系统给搞崩了,被老板爆怼一顿!
王树尧老师运筹学课程笔记 06 线性规划与单纯形法(几何意义)
Flink实时仓库-DWD层(处理复杂数据-流和表的装换处理)模板代码
图像加噪声与矩阵求逆
王树尧老师运筹学课程笔记 09 线性规划与单纯形法(单纯形表的应用)
Connecting PHP 7.4 to Oracle configuration on Windows
模拟卷Leetcode【普通】222. 完全二叉树的节点个数
数仓建模,什么是宽表?如何设计?好处与不足
Unity免费元素特效推荐
Flink实时仓库-DWD层(流量域)模板代码
ECCV 2022 lightweight model frame Parc net press apple mobilevit code and paper Download
模拟卷Leetcode【普通】093. 复原 IP 地址
leetcode-592:分数加减运算
MySql基础知识(高频面试题)