最近在开发DAdolfans的时候遇到了这么个需求:监听一个contentEditable
的div
内容变化。
我们知道,监听textarea
或者input
内容的变化通过简单的jq
监听就能做到,但是如果监听的对象是一个div
的话它们就无能为力了。上网查了几个方法:
click keyup blur
三个事件,如果触发了这三个事件就视作内容发生了变化,这个方法的缺点非常明显,你按下ctrl
都会算做内容变化了。看到这简单粗暴的处理方法当时的我都被吓尿了٩(ŏ﹏ŏ、)۶,不过还是乖乖的用了这货……
第二种方法是把div
的内容扔一个变量里,用setsetInterval
高频扫描。唔,其实这样也是一种解决方法啦……不过百万字级别的文档这么扫明显还是比较吃资源的_(¦3」∠)_
第三种方法是DOMNodeInserted
事件,当DOM
有插入节点的行为时触发,不过……Σ(゚∀゚ノ)ノ 麻麻这个会漏判好多东西好嘛!如果我不插入新的Node而是编辑一个现有的Node它不会有反应啊:(´ཀ`」 ∠): 。
之后,昨天,在知乎上一篇毫不相干的文章中看到了这么个玩意,叫MutationObserver
,MDN(文章末尾有地址)上对它的定义是这么说的:
MutationObserver
给开发者们提供了一种能在某个范围内的DOM树发生变化时作出适当反应的能力.该API设计用来替换掉在DOM3事件规范中引入的Mutation
事件.
看了下简介,新引入的东西,兼容性肯定不好,不过本着旧版本浏览器干我P事的原则我在最新版本的各个浏览器试了一下d(・∀・)b,
window.MutationObserver`均可用。
这里强调一下所谓的可用是不需要引用私有方法,MDN上的代码已经过于陈旧,我说的是这行:
1 | var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver |
最新的版本已经不需要后面的两个了,在火狐下定义一个Moz开头的会直接报Undefined
,Webkit(其实是Blink)下前两个都能返回正确的结果。所以去参考MDN的孩子们注意一下这里。
然后说一下用法,MDN说的非常明白,这里就简单复述下在前面提到的需求:监听一个contentEditable
的div
内容变化,这货怎么写。
选择一个要去监控的对象:
1 | mainArea = document.querySelector("#main_area"); |
querySelector
是个新玩意,是JS原生的内容,做到像jQuery选择器一样,用类似css的选择方式去选择元素;当听说这玩意出现的时候我流下了两行热泪(;´ ༎ຶ Д ༎ຶ`)σ selectElementById
再见……
之后实例化一个MutationObserver
1 | MutationObserver = window.MutationObserver |
之后需要告诉这个观察者你需要观察的内容:
1 | DocumentObserverConfig = { |
监听的内容包括div
的attr
发生变化、子节点发生了变化、文本节点发生了变化、子节点的后代发生变化。
当上述变化发生时激活回调函数。
接下来开始监听:
1 | DocumentObserver.observe(mainArea, DocumentObserverConfig); |
这样它就会开始监听了。
不过其实这个函数并不是拿来干这个的……它是用来追踪元素内容变化过程的,所以队列里会积累一些东西。为了节省资源我们可以定义一个释放方法:
1 | function refreshObserver() { |
之后适当的时间释放一下就好了。
没了(∫・ω・)∫
参考资源:https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver
Comments
No comments here,
Why not write something?