使用 MutationObserver 监听 DOM 元素变化

发布:elantion 日期:2019-12-19 阅读:310 评论:0

最近在写一些入侵式的代码时,需要监听 DOM 元素的变化,于是用到了 MutationObserver 方法,但具体在使用中遇到很多问题,所以这里记录下来,以便以后查看。

兼容问题

MuationObserver 支持 Chrome 18+(18 - 26 需要 webkit 前缀),IE 11+,现代浏览器都能很好地支持,所以不用太在意兼容性问题,如果想尽可能的兼容多版本,可以使用以下代码。

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

使用方法简述

就像标题说的,主要就是监听DOM元素的变化,包括DOM的增删改查,属性的改变,文本的改变。使用方法很简单,看下面代码:

// 设置监听的回调函数,当DOM的改变符号预设时,就会执行这个回调函数
const callback = () => {
	console.log('dom change');
};
// 把回调函数传给构建函数
const observer = new MutationObserver(callback);
// 查找需要监听的元素
const targetEl = document.querySelector('.title');
// 监听参数,需要监听什么,需要监听的范围都在这儿设置
const config = {
	// 是否需要监听元素的属性,默认否
	attributes: true,
	// 设置只监听的属性,例如class名,默认空
	attributeFilter: ['class'],
	// 是否需要记住属性改变前的值,默认否
	attributeOldValue: false,
	// 是否需要监听元素内文本的变化,默认否
	characterData: false,
	// 是否需要记住元素内文本变化前的值,默认否
	characterDataOldValue: false,
	// 是否需要监听元素下一级的DOM的变化,例如增加或删除,默认否
	// 如果下面subtree为true时,就会监内元素内所有的DOM的变化
	childList: false,
	// 是否需要监听元素内所有元素的变化,默认否
	subtree: false,
};
// 
observer.observe(targetEl, config);

触发条件

上面的代码会在.title元素改变style的值时,执行callback,例如:

const titleEl = document.querySelector('.title');
titleEl.style.fontSize = '16px';
// -> dom change

如果改变config的值,就可以改变你想监听的目标,例如,你想监听元素内是否有增加DOM,那就可以把config改成这样:

const config = {
	childList: trrue,
	subtree: true,
};

这样,.title元素内增加或删除元素都会触发回调函数,更多的玩法,大家可以慢慢去探索。

多重监听

如果回调函数是一样的,但监听的目标不同,可以设置多个监听点,例如:

obserser.observe(document.querySelector('.title'), { attributes: true });
observer.observe(document.querySelector('.content'), { childList: true, subtree: true });

这样,当.title的属性改变或者.content内添加删除元素都会触发回调函数。

解除监听

为了节省性能,在不需要监听时,可以移除监听,如下:

observer.disconnect();

执行之后,之前对.ttile.content的监听都会解除。

移除未执行回调的记录

有时候一次性改变多个元素,会多次执行回调函数callback,如果你只想执行一次回调,可以使用takeRecords方法,这个方法会返回未处理的改变记录,然后清空将要执行回调的队列。

observer.takeRecords();

reference

https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver