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);

.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 突变监视器的更多相关文章

  1. NeHe OpenGL教程 第二十四课:扩展

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  2. javaSE第二十四天

    第二十四天    363 1:多线程(理解)    363 (1)JDK5以后的Lock锁    363 A:定义    363 B:方法:    364 C:具体应用(以售票程序为例)    364 ...

  3. Python第二十四天 binascii模块

    Python第二十四天 binascii模块 binascii用来进行进制和字符串之间的转换 import binascii s = 'abcde' h = binascii.b2a_hex(s) # ...

  4. Gradle 1.12用户指南翻译——第二十四章. Groovy 插件

    其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://g ...

  5. SQL注入之Sqli-labs系列第二十四关(二阶注入)

    开始挑战第二十四关(Second Degree Injections) 0x1 前言 SQL注入一般分为两类:一阶SQL注入(普通SQL注入),二阶SQL注入 .二次注入不是注入两次的意思,请不要混淆 ...

  6. “全栈2019”Java多线程第二十四章:等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  7. “全栈2019”Java第二十四章:流程控制语句中决策语句switch下篇

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  8. 孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘

    孤荷凌寒自学python第二十四天python类中隐藏的私有方法探秘 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 今天发现了python的类中隐藏着一些特殊的私有方法. 这些私有方法不管我 ...

  9. 第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题

    第二十四届全国青少年信息学奥林匹克联赛初赛 普及组C++语言试题 1.原题呈现 2.试题答案 3.题目解析 因博客园无法打出公式等,所以给你们几个小编推荐的链接去看看,在这里小编深感抱歉! https ...

随机推荐

  1. Quartz.net 3.x使用总结(二)——Db持久化和集群

    上一篇简单介绍了Quartz.net的概念和基本用法,这一篇记录一下Quartz.net通过数据库持久化Trigger和Jobs等数据,并简单配置Quartz.net的集群. 1.JobStore介绍 ...

  2. Mysq登陆后执行命令提示You must SET PASSWORD before executing this statement

    mysql  安装完成后,在输入命令行时,提示:You must SET PASSWORD before executing this statement 提示必须设置密码,我想不是已经设置了密码吗? ...

  3. 修改WEB项目的发布名称

    1.在要修改的项目上单击右键选择properties,修改web选项中的Web Context-root中的发布名称即可,但需要注意的是修改发布名称后需要将项目从服务器中先移除后再重新添加.

  4. vue安装scss,并且全局引入

    在写vue的css样式时,觉得需要css预处理器让自己的css更加简洁.适应性更强.可读性更佳,更易于代码的维护,于是在vue-cli脚手架采用scss.写过的人都知道,每写一个.vue文件都要在st ...

  5. Java 计算两个日期相差月数、天数

    package com.myjava; import java.text.ParseException; import java.text.SimpleDateFormat; import java. ...

  6. 电子医疗设备创新研发应该用i.MX6Q开发板吗?为医疗设备提供解决方案

    伴随医疗信息化.移动化.智能化的不断发展,居民对自身健康的关注度持续加强,全球医疗电子产业近年来持续保持快速增长态势.同时,源于庞大的人口基数以及迅速增长的老龄化人口带来持续增长的医疗服务需求,加之全 ...

  7. ASP .NET Core HTTP Error 502.5 – Process Failure

    页面返回错误 事件日志显示错误 大家可以先看着个链接 https://docs.microsoft.com/en-us/aspnet/core/publishing/iis?tabs=aspnetco ...

  8. 51nod--1135 原根 (数论)

    题目: 设m是正整数,a是整数,若a模m的阶等于φ(m),则称a为模m的一个原根.(其中φ(m)表示m的欧拉函数) 给出1个质数P,找出P最小的原根. Input 输入1个质数P(3 <= P ...

  9. JavaScript读取对象属性遇到的问题

    JavaScript中对于对象的属性存取方式有两种:“.”操作和[]操作. “.”操作属性名通常直接写,[]操作中属性的名字通常要加引号, 而当需要读取的对象属性名是一个变量的时候,一般使用[]操作, ...

  10. form表单获取多选的值

    flask 中 form 表单直接获取多选框的值时 language = request.values.getlist('values')或 language=request.from.getlist ...