使用 MutationObserver 跟踪 DOM 的变化

=Start=

缘由:

真的是隔行如隔山,虽然都属于IT行业,但是我对于前端的很多东西都不了解(尤其是近些年前端的发展变化日新月异),好后悔之前没有好好学习前端的知识……

这里简单记录一下前段时间了解到的MutationObserver这个知识点,方便以后要用的时候参考。

正文:

参考解答:
一、DOM是什么?

当网页被加载时,浏览器会创建页面的文档对象模型(DOM, Document Object Model)。通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素。通过可编程的对象模型,JavaScript 获得了足够的能力来创建动态的 HTML。

二、如何监听DOM的变化?
  • 轮询(Polling)
  • MutationEvents
  • CSS animations
  • MutationObserver
三、MutationObserver的方案

Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。

概念上,它很接近事件,可以理解为 DOM 发生变动就会触发 Mutation Observer 事件。但是,它与事件有一个本质不同:事件是同步触发,也就是说,DOM 的变动立刻会触发相应的事件;Mutation Observer 则是异步触发,DOM 的变动并不会马上触发,而是要等到当前所有 DOM 操作都结束才触发。

这样设计是为了应付 DOM 变动频繁的特点。举例来说,如果文档中连续插入1000个 元素,就会连续触发1000个插入事件,执行每个事件的回调函数,这很可能造成浏览器的卡顿;而 Mutation Observer 完全不同,只在 1000 个段落都插入结束后才会触发,而且只触发一次。

Mutation Observer有以下特点:

  1. 它等待所有脚本任务完成后,才会运行,即采用异步方式
  2. 把 DOM 变动记录封装成一个数组进行处理,而不是一条条地个别处理 DOM 变动
  3. 既可以观察发生在 DOM 节点的所有变动,也可以观察某一类变动
四、一个简单的样例
<!DOCTYPE html>
<html>
<head>
	<title>MutationObserver-test</title>
	<script type="text/javascript">
// 选择需要观察变动的节点
var targetNode = document.getElementById('uniq_id_name');

// 观察器的配置(需要观察什么变动)
const config = { attributes: true, childList: true, subtree: true };

// 当观察到变动时执行的回调函数
const callback = function(mutationsList, observer) {
    // Use traditional 'for loops' for IE 11
    for(let mutation of mutationsList) {
        if (mutation.type === 'childList') {
            console.log('A child node has been added or removed.');
        }
        else if (mutation.type === 'attributes') {
            console.log('The ' + mutation.attributeName + ' attribute was modified.');
        }
        console.log(mutation);
    }
};

// 创建一个观察器实例并传入回调函数
const observer = new MutationObserver(callback);

// 以上述配置开始观察目标节点
// observer.observe(targetNode, config); /* Uncaught TypeError: Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'. */
observer.observe(document, config); /* 第一个参数试了很多,发现只能是 document 才不会报错…… */

// 之后,可停止观察
// observer.disconnect();
	</script>
</head>

<body>
	<div id="uniq_id_name">
		this is original div's content.
	</div>
</body>

</html>

五、MutationObserver的实际使用场景
  • 你希望通知 Web 应用程序访问者,他当前所在的页面发生了一些更改。
  • 你正在开发一个新的 JavaScript 框架,需要根据 DOM 的变化动态加载 JavaScript 模块。
  • 也许你正在开发一个所见即所得(WYSIWYG) 编辑器,试图实现撤消/重做功能。通过利用 MutationObserver API,你可以知道在任何给定的点上进行了哪些更改,因此可以轻松地撤消这些更改。
  • 还有给页面添加水印的时候,防止一些不怀好意的人对水印的元素做手脚来修改或隐藏水印。
参考链接:

JavaScript HTML DOM
https://www.runoob.com/js/js-htmldom.html

https://developer.mozilla.org/zh-CN/docs/Web/API/MutationObserver

https://wangdoc.com/javascript/dom/mutationobserver.html

JavaScript是如何工作的:使用MutationObserver跟踪DOM的变化
https://blog.fundebug.com/2019/01/10/understand-mutationobserver/
https://blog.sessionstack.com/how-javascript-works-tracking-changes-in-the-dom-using-mutationobserver-86adc7446401

Mutation Observer 的三个实际应用
https://www.zcfy.cc/article/three-real-world-uses-for-mutation-observer
https://eager.io/blog/three-real-world-use-cases-for-mutation-observer/

canvas 生成页面水印,MutationObserver 控制节点防修改
https://www.liangzl.com/get-article-detail-134311.html

制作水印
https://www.dazhuanlan.com/2020/03/15/5e6d69a58de32/
https://www.cnblogs.com/jscode/p/3600060.html

前端水印初探
https://www.mdeditor.tw/pl/2RBr

页面水印插件开发
http://www.wuhub.top/the-development-of-page-watermark/

https://stackoverflow.com/questions/tagged/mutation-observers?tab=Votes

Detect changes in the DOM
https://stackoverflow.com/questions/3219758/detect-changes-in-the-dom

=END=

声明: 除非注明,ixyzero.com文章均为原创,转载请以链接形式标明本文地址,谢谢!
https://ixyzero.com/blog/archives/5047.html

《使用 MutationObserver 跟踪 DOM 的变化》上的一个想法

  1. 阿里巴巴公司根据截图查到泄露信息的具体员工的技术是什么?
    https://www.zhihu.com/question/50735753

    阿里巴巴内网的不可见水印用的是什么算法?
    https://www.zhihu.com/question/50677827/answer/122239863
    `
    在阿里实习的时候,分析过这个东西,当然只是纯好奇技术啦。对外公开内网的信息本身就是不道德的,而且可能触犯保密协议。

    首先,第一道防线。看截图这个人是用阿里内外的iOS客户端截的图,且不说截下来的图 PS 能不能完整去水印。在截图操作的瞬间,客户端首先就能感知到你有没有截图。 iOS 有这个 API,Android 也能通过监听截图保存路径实现 ,做过移动端开发的人应该都有所了解。所以你在什么时间、什么页面截了图,其实都能记录下来并上传服务器的。可参考:
    RxScreenshotDetector:Android 截屏检测
    iOS开发-检测用户截屏, 并获取所截图片

    再者,第二道防线。在手机客户端截图是不方便去水印的。水印其实就是写着工号的透明度很高的图片,background-image 的方式平铺满整个屏幕。如果在 chrome里,直接审查元素去掉就行,这样就去除干净了。如果先截了图,再用 PS 去除的话,就有点麻烦了。因为用 PS 去除的话很容易漏掉一些东西,比如工号二进制。

    (很多人不理解水印的原理,这里多解释几句,这种高透明度的水印从正面看屏幕的话肉眼很难看到。从屏幕上下斜看,也能隐约看到一些。在 PS 里调下色阶马上就显现出来了。

    第三道防线,很多人知道这个水印里有工号,但不知道还有工号的二进制。就是用.和/组成的二进制,和工号放在一张图片里。工号的水印调调对比度、色阶,甚至斜着看屏幕就能看到,但是“./”组成的二进制又小又隐蔽,所以用 PS 的话很容易漏掉。

    最后一道防线,还记得之前阿里 HR 伪造员工离职谈话的那个风波的时候。即便一个懂前端的程序员去除了水印,最后还是被查出来了,这是为什么?个人推测,可能是根据截图中的评论数、芝麻数等等随着时间变化的数据,反推出截图的时间区间,然后根据时间筛选访问这个帖子的访问日志,缩小范围到几个人,再逐个约谈,大概就能确定了。

    很多知友说通过背景色差、文字段落间距、排版什么的就有点太高端了,阿里目前应该不会用到吧……

    至于中间人监控员工上网信息,这个不了解还是别不推测了……
    `

发表评论

邮箱地址不会被公开。 必填项已用*标注