(91)Wangdao.com第二十四天_Mutation Observer API 突变监视器
Mutation Observer API 突变监视接口
用来监视 DOM 变动。
DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知
概念上,它很接近事件,可以理解为 DOM 发生变动就会触发 Mutation Observer 事件。
但是,Mutation Observer 与 事件 有一个本质不同:
- 事件是同步触发,也就是说,DOM 的变动立刻会触发相应的事件;
- Mutation Observer 则是异步触发,DOM 的变动并不会马上触发,而是要等到当前所有 DOM 操作都结束才触发
Mutation Observer 有以下特点:
- 它等待所有脚本任务完成后,才会运行(即异步触发方式)。
- 它把 DOM 变动记录封装成一个数组进行处理,而不是一条条个别处理 DOM 变动。
- 它既可以观察 DOM 的所有类型变动,也可以指定只观察某一类变动。
Mutation Observer 构造函数
- 使用
- 使用 MutationObserver 构造函数,新建一个观察器实例,同时指定这个实例的回调函数。
var box = document.getElementById("test_box"); // 1. 定义一个 监视器 实例
var mo = new MutationObserver(function(mutations, observer){
mutations.forEach(function(mutation){
console.log(mutation);
});
}); // 2. 定义要监听的 类型集合 对象
var chgType = {
"childList": true, // 子节点变动 监视
"attributes": true, // 属性变动 监视
"characterData": true, // 节点内容 或者 节点文本 的变动
}; // 3. 启动监听
mo.observe(box, chgType);
- 使用 MutationObserver 构造函数,新建一个观察器实例,同时指定这个实例的回调函数。
.observe() 启动监视器
- 第一个参数是 所要观察的DOM元素是article
- 第二个参数是 所要观察的变动类型
至少指定一种要监听的变动类型,否则报错
"childList": true, 子节点 变动
"attributes": true, 属性 变动
"characterData": true, 节点内容 或者 节点文本 变动
还可指定监听属性
"subtree": true, 是否同时监视该节点的所有后代节点
"attributeOldValue": true, 监视 attributes 变动时,是否需要记录变动前的属性值
"characterDataOldValue": true, 监视 characterData 变动时,是否需要记录变动前的属性值
"attributeFilter": 数组, 表示需要观察的特定属性(比如['class','src'])
- 实例:观察新增的子节点
var insertedNodes = [];
var mo = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
for (var i = 0; i < mutation.addedNodes.length; i++)
insertedNodes.push(mutation.addedNodes[i]);
})
});
mo.observe(document, { childList: true });
console.log(insertedNodes);
.disconnect(); 停止监视
.takeRecords(); 清除变动记录,即不再处理未处理的变动____该方法返回变动记录的数组
// 保存所有没有被观察器处理的变动
var changes = mutationObserver.takeRecords();
MutationRecord 对象
DOM 每次发生变化,就会生成一条变动记录(MutationRecord 实例)。该实例包含了与变动相关的所有信息。
Mutation Observer 处理的就是一个个 MutationRecord 实例所组成的数组
- MutationRecord 对象包含了 DOM 的相关信息,有如下属性:
type 观察的 突变类型(attributes、characterData 或者 childList)
target 发生突变的 DOM 节点
addedNodes 新增的 DOM 节点
removedNodes 删除的 DOM 节点
previousSibling 前一个同级节点,如果没有则返回 null
nextSibling 下一个同级节点,如果没有则返回 null
attributeName 发生突变的属性。如果设置了 attributeFilter,则只返回预先指定的属性
oldValue 突变前的值。这个属性只对 attribute 和 characterData 突变有效,如果发生 childList 突变,则返回 null
- 实例: 观察<body>的所有下级节点, 回调函数会在控制台显示所有变动的类型和目标节点
var callback = function (records){
records.map(function(record){
console.log('Mutation type: ' + record.type);
console.log('Mutation target: ' + record.target);
});
}; var mo = new MutationObserver(callback); var chgType = {
'childList': true,
'subtree': true
}; mo.observe(document.body, chgType);- 实例: 属性变动('attributes': true), 实际发生变动时,会将变动前的值显示在控制台。
var callback = function (records) {
records.map(function (record) {
console.log('Previous attribute value: ' + record.oldValue);
});
}; var mo = new MutationObserver(callback); var element = document.getElementById('#my_element'); var options = {
'attributes': true,
'attributeOldValue': true
} mo.observe(element, options);
- 封装: 目标元素 只要在 DOM 上已加载, 则执行 fn
(function(win){
'use strict';
var doc = win.document;
var MutationObserver = win.MutationObserver || win.WebKitMutationObserver; var targets = [];
var mo; function isReadyOrNot(){
// 检查是否匹配已储存的节点
for(var i = 0; i < targets.length; i++){
var target = targets[i];
var elements = doc.querySelectorAll(target.selector); // 检查指定节点是否有匹配
for(var j = 0; j < elements.length; j++){
var element = elements[j]; // 确保回调函数只会对该元素调用一次
if(!element.isReady){
element.isReady = true;
// 对该节点调用回调函数
target.fn.call(element, element);
};
};
};
}; /**** 目标元素 只要在 DOM 上已加载, 则执行 fn ****/
win.eleReady = function(selector, fn){
// 储存选择器和回调函数
targets.push({
selector: selector,
fn: fn
}); if(!mo){
mo = new MutationObserver(isReadyOrNot); // 定义 突变监听器
mo.observe(doc.documentElement, { // 开始监听 document变化
childList: true, // 监听 子节点
subtree: true // 同时监听 后代节点
});
}; isReadyOrNot(); // 检查该节点是否已经在DOM中
};
})(window); eleReady('.foo', function(element){
// ...
});
(91)Wangdao.com第二十四天_Mutation Observer API 突变监视器的更多相关文章
- NeHe OpenGL教程 第二十四课:扩展
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- javaSE第二十四天
第二十四天 363 1:多线程(理解) 363 (1)JDK5以后的Lock锁 363 A:定义 363 B:方法: 364 C:具体应用(以售票程序为例) 364 ...
- Python第二十四天 binascii模块
Python第二十四天 binascii模块 binascii用来进行进制和字符串之间的转换 import binascii s = 'abcde' h = binascii.b2a_hex(s) # ...
- Gradle 1.12用户指南翻译——第二十四章. Groovy 插件
其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...
- SQL注入之Sqli-labs系列第二十四关(二阶注入)
开始挑战第二十四关(Second Degree Injections) 0x1 前言 SQL注入一般分为两类:一阶SQL注入(普通SQL注入),二阶SQL注入 .二次注入不是注入两次的意思,请不要混淆 ...
- “全栈2019”Java多线程第二十四章:等待唤醒机制详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java第二十四章:流程控制语句中决策语句switch下篇
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘
孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天发现了python的类中隐藏着一些特殊的私有方法. 这些私有方法不管我 ...
- 第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题
第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题 1.原题呈现 2.试题答案 3.题目解析 因博客园无法打出公式等,所以给你们几个小编推荐的链接去看看,在这里小编深感抱歉! https ...
随机推荐
- HDU 5984(求木棒切割期望 数学)
题意是给定一长为 L 的木棒,每次任意切去一部分直到剩余部分的长度不超过 D,求切割次数的期望. 若木棒初始长度不超过 D,则期望是 0.000000: 设切割长度为 X 的木棒切割次数的期望是 F( ...
- [物理学与PDEs]第5章第4节 本构方程 - 应力与变形之间的关系
5. 4 本构方程 - 应力与变形之间的关系 5.4.1. 本构关系的一般形式 1. 若 Cauchy 应力张量 ${\bf T}$ 满足 $$\bex {\bf T}({\bf y})=\hat{\ ...
- requests session operation
# encoding:utf-8# baseic usage of requests.sessionsimport requestsfrom requests import sessions r = ...
- 基于vue cli 3.0创建前端项目并安装cube-ui
前提条件: 安装node.js. 国内的开发者最好先配置淘宝镜像. 之后用cnpm来代替npm命令. 项目创建过程: 打开cmd,输入命令进入目标工作空间,以本机项目为例: cd /d d: cd D ...
- 「CTSC2018」暴力写挂
毫无$ Debug$能力 全世界就我会被卡空间.jpg LOJ #2553 UOJ #400 Luogu P4565 题意 给定两棵树$ T,T'$,求一组点对$ (x,y)$使得$deep(x)+d ...
- java 面经
1.什么是Java虚拟机(JVM)?为什么Java被称作是“平台无关的编程语言”? Java虚拟机是一个可以执行Java字节码的虚拟机进程.Java源文件被编译成能被Java虚拟机执行的字节码文件. ...
- java应用的优化【转】
XX银行网银系统是一套全新的对公业务渠道类系统,经过两年的建设,将逐步对外提供服务. 该系统融合了原来多个对公渠道系统,并发量是以前多个系统之和,吞吐量要求将大幅上升.为了使广大对公客户使用系统时获得 ...
- oracle用命令创建表空间、用户,并为用户授权、收回权限。
oracle中如何删除用户? Oracle中使用DROP USER来删除用户,如果使用DROP USER CASCADE那么用户的对象也同时被删除掉.为了达到删除用户的效果而又不影响对用户下的对象的使 ...
- 【easy】206. Reverse Linked List 链表反转
链表反转,一发成功~ /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; ...
- jenkins中slave节点连接的两种常用方式
我们在使用jenkins的时候,一般来说肯定是有slave节点的,本来网上也有好多关于jenkins节点配置的教程,我也就不写了.简单说明一下:任务一般是在slave上面运行的.当然不是讲master ...