资讯专栏INFORMATION COLUMN

js mutationobserver简要介绍

leone / 2786人阅读

摘要:观察者模式介绍观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。

观察者模式介绍
观察者设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,
所有依赖于它的对象都得到通知并自动刷新。

一些好的文章
观察者模式与委托模式的区别
深入理解JavaScript系列(32):设计模式之观察者模式
【Javascript设计模式3】-观察者模式

MutationObserver介绍

可以使用的配置

childList: *true =========================可以观察子元素

attributes: *true ========================可以观察属性

characterData: *true ====================可以观察数据

subtree: *true =========================可以观察所有后代

attributeOldValue: *true ==================可以保存属性旧值

characterDataOldValue: ==================*true 可以保存数据旧值

attributeFilter: ==========================设置指定观察属性元素集合

  

note: Mutation Observers 被限制可以观察Dom序列化状态 在观察textarea内内容改变时 无法触发

observe 一个被观察者对象 一份配置

void observe(
  Node target,
  MutationObserverInit options
);

disconnet 断开观察者与目标链接

void disconnect();

takeRecords 返回对象所有观察记录

Array takeRecords();
MutationObserver使用

不同浏览器之间存在兼容性问题

  var MutationObserver = window.MutationObserver 
|| window.WebKitMutationObserver 
|| window.MozMutationObserver;

html

  
  1. Press enter and look at the console

获取list dom

var list = document.querySelector("ol");

实例化MutationObserver

var Observer = new MutationObserver(function(mutations){
});

Mutation Observer 对象

监测childList

Observer.observe(list, {
  childList: true
});

不过值得注意的是 这里观测的是list直接child 如果要观测child的child 就需要开启subtree
比如要检测这样的行为

list.childNodes[0].appendChild(document.createElement("div"));

observer需要更改配置

Observer.observe(list, {
  childList: true,
  subtree: true
});

(mutationObserver观测childlist) jsbin地址

observe 常见配置 及其解释

observer.observe(target, {childList:true,subtree:true})                 
//subtree属性让观察行为进行"递归",这时,以target节点为根节点的整棵DOM树发生的变化都可能会被观察到 
observer.observe(document, {childList:true,subtree:true})               
//如果target为document或者document.documentElement,则当前文档中所有的节点添加与删除操作都会被观察到
observer.observe(document, {childList:true,attributes:true,characterData:true,subtree:true})   
//当前文档中几乎所有类型的节点变化都会被观察到(包括属性节点的变化和文本节点的变化等)

observe 观察characterData

Observer.observe(list, {childList:true});  
//假设此时target的outHTML内容为
foo
,则: list.childNodes[0].data = "bar"; //不会触发回调函数,因为childList只观察节点的新建与删除, 而这里target节点的子节点仍然只有一个,没有多,没有少 Observer.observe(list, { childList:true,characterData:true}); //加上characterData属性,允许观察文本节点的变化,行不行? list.childNodes[0].data = "sds"; //还是不会触发回调函数,因为发生变化的是target节点的子节点,我们目前的目标节点只有一个,就是target. Observer.observe(list, { childList:true,characterData:true,subtree:true}); //加上subtree属性,观察所有后代节点 list.childNodes[0].data = "cha";

(mutationObserver观测characterdata) jsbin地址

observe 观察attribute

Observer.observe(list, {attributes:true});                    
//只观察目标节点的属性节点
list.setAttribute("foo","bar");        
//不管foo属性存在不存在,都会触发回调函数
list.setAttribute("foo","bar");        
//即使前后两次的属性值一样,还是会触发回调函数
list.removeAttribute("foo");            
//移除foo属性节点,触发回调函数
list.removeAttribute("foo");            
//不会触发回调函数,因为已经没有属性节点可移除了
Observer.observe(list, {attributes:true,attributeFilter:["bar"]});     
//指定要观察的属性名
list.setAttribute("foo","bar");        
//不会触发回调函数,因为attributeFilter数组不包含"foo"
list.setAttribute("bar","foo"); 

(mutationObserver观测attribute) jsbin地址

我们开始做一个编辑器

功能 向前 向后并且按钮要能随时改变

ol设置为contenteditable时,当每次敲击回车时,ol的children会增加一个li 并且我们构造一个observer监听它子元素的变化, 这样我们便可以获得每次改变后所有新的children

  var observer = new MutationObserver(function(mutations) {  
    mutations.forEach(function(mutation) {
      if (mutation.type === "childList") {
        var list_values = [].slice.call(list.children) 
            .map( function(node) { return node.innerHTML; }) 
            .filter( function(s) {
              if (s === "
") { return false; } else { return true; } }); console.log(list_values); } }); }); observer.observe(list, { attributes: true, childList: true, characterData: true });

(观察ol子元素的变化) jsbin地址

编辑器对与每行变化也需要监测, 我们可以自己构造一个entry保存每次数据

var observer = new MutationObserver(function (mutations) {
    // Whether you iterate over mutations..
    mutations.forEach(function (mutation) {
      // or use all mutation records is entirely up to you
      var entry = {
        mutation: mutation,
        el: mutation.target,
        value: mutation.target.textContent,
        oldValue: mutation.oldValue
      };
      console.log("Recording mutation:", entry);
    });
  });

(ol监测每一行变化) jsbin地址

编辑器统计字数

var observer = new  MutationObserver(function(mutations){ mutations.forEach(function(mutation){
    if(mutation.type == "characterData") {
    var newValue = mutation.target.textContent;
      textinputcount.innerHTML = "还可以输入"+(1000 - newValue.length+"字");
    }
  });

编辑器统计字数

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85815.html

相关文章

  • 简要总结microtask和macrotask

    摘要:众所周知和都属于上述异步任务的一种那到底为什么和会有顺序之分这就是我想分析总结的问题所在了和的作用是为了让浏览器能够从内部获取的内容并确保执行栈能够顺序进行。只要执行栈没有其他在执行,在每个结束时,队列就会在回调后处理。 前言 我是在做前端面试题中看到了setTimeout和Promise的比较,然后第一次看到了microtask和macrotask的概念,在阅读了一些文章之后发现没有...

    yexiaobai 评论0 收藏0
  • js监听div元素的宽高变化

    摘要:构造函数,参数为回调函数构造函数为,它在监听到中的改变并且一系列改变结束后触发回调函数。是要监听的元素,为监听选项对象,可选的选项如下所以监听元素宽高变化,就是监听属性变化这样当元素发生变化时,就会触发构造函数中的函数。 一、js监听window变化的方法 1、onsize只能监听window对象的变化 (1)、 window对象原生、jQuery方法 //原生写法 window.on...

    lansheng228 评论0 收藏0
  • 浅析 Vue 2.6 中的 nextTick 方法

    摘要:核心的异步延迟函数,用于异步延迟调用函数优先使用原生原本支持更广,但在的中,触摸事件处理程序中触发会产生严重错误的,回调被推入队列但是队列可能不会如期执行。 浅析 Vue 2.6 中的 nextTick 方法。 事件循环 JS 的 事件循环 和 任务队列 其实是理解 nextTick 概念的关键。这个网上其实有很多优质的文章做了详细介绍,我就简单过过了。 以下内容适用于浏览器端 JS,...

    fobnn 评论0 收藏0
  • JavaScript Event Loop 机制详解与 Vue.js 中实践应用

    摘要:机制详解与中实践应用归纳于笔者的现代开发语法基础与实践技巧系列文章。事件循环机制详解与实践应用是典型的单线程单并发语言,即表示在同一时间片内其只能执行单个任务或者部分代码片。 JavaScript Event Loop 机制详解与 Vue.js 中实践应用归纳于笔者的现代 JavaScript 开发:语法基础与实践技巧系列文章。本文依次介绍了函数调用栈、MacroTask 与 Micr...

    livem 评论0 收藏0
  • Event Loop执行顺序

    摘要:简要介绍谈谈在队列中的执行顺序问题的来源都不陌生,是指主线程从任务队列中循环读取任务,比如例输出在上述的例子中,我们明白首先执行主线程中的同步任务,当主线程任务执行完毕后,再从中读取任务,因此先输出,再输出。 简要介绍:谈谈promise.resove,setTimeout,setImmediate,process.nextTick在EvenLoop队列中的执行顺序 问题的来源 eve...

    kk_miles 评论0 收藏0

发表评论

0条评论

leone

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<