主页 > 前端 > javascript > webapi >
来源:未知 时间:2024-05-12 19:45 作者:小飞侠 阅读:次
[导读] 概述 Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。 概念上,它很接近事件,可以理解为 DOM 发生变动...
概述Mutation Observer API 用来监视 DOM 变动。DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,这个 API 都可以得到通知。 概念上,它很接近事件,可以理解为 DOM 发生变动就会触发 Mutation Observer 事件。但是,它与事件有一个本质不同:事件是同步触发,也就是说,DOM 的变动立刻会触发相应的事件;Mutation Observer 则是异步触发,DOM 的变动并不会马上触发,而是要等到当前所有 DOM 操作都结束才触发。 这样设计是为了应付 DOM 变动频繁的特点。举例来说,如果文档中连续插入1000个<p>元素,就会连续触发1000个插入事件,执行每个事件的回调函数,这很可能造成浏览器的卡顿;而 Mutation Observer 完全不同,只在1000个段落都插入结束后才会触发,而且只触发一次。 Mutation Observer 有以下特点。
MutationObserver 构造函数使用时,首先使用MutationObserver构造函数,新建一个观察器实例,同时指定这个实例的回调函数。 var observer = new MutationObserver(callback); 上面代码中的回调函数,会在每次 DOM 变动后调用。该回调函数接受两个参数,第一个是变动数组,第二个是观察器实例,下面是一个例子。 var observer = new MutationObserver(function (mutations, observer) {
mutations.forEach(function(mutation) {
console.log(mutation);
});
});MutationObserver 的实例方法 observe()observe方法用来启动监听,它接受两个参数。
var article = document.querySelector('article');
var options = {
'childList': true,
'attributes':true} ;
observer.observe(article, options);上面代码中,observe方法接受两个参数,第一个是所要观察的DOM元素是article,第二个是所要观察的变动类型(子节点变动和属性变动)。 观察器所能观察的 DOM 变动类型(即上面代码的options对象),有以下几种。
想要观察哪一种变动类型,就在option对象中指定它的值为true。需要注意的是,必须同时指定childList、attributes和characterData中的一种或多种,若未均指定将报错。 除了变动类型,options对象还可以设定以下属性:
// 开始监听文档根节点(即<html>标签)的变动mutationObserver.observe(document.documentElement, {
attributes: true,
characterData: true,
childList: true,
subtree: true,
attributeOldValue: true,
characterDataOldValue: true});对一个节点添加观察器,就像使用addEventListener方法一样,多次添加同一个观察器是无效的,回调函数依然只会触发一次。但是,如果指定不同的options对象,就会被当作两个不同的观察器。 下面的例子是观察新增的子节点。 var insertedNodes = [];
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
for (var i = 0; i < mutation.addedNodes.length; i++)
insertedNodes.push(mutation.addedNodes[i]);
})});
observer.observe(document, { childList: true });
console.log(insertedNodes);disconnect(),takeRecords()disconnect方法用来停止观察。调用该方法后,DOM 再发生变动,也不会触发观察器。 observer.disconnect(); takeRecords方法用来清除变动记录,即不再处理未处理的变动。该方法返回变动记录的数组。 observer.takeRecords(); 下面是一个例子。 // 保存所有没有被观察器处理的变动 var changes = mutationObserver.takeRecords(); // 停止观察 mutationObserver.disconnect(); MutationRecord 对象DOM 每次发生变化,就会生成一条变动记录(MutationRecord 实例)。该实例包含了与变动相关的所有信息。Mutation Observer 处理的就是一个个MutationRecord实例所组成的数组。 MutationRecord对象包含了DOM的相关信息,有如下属性:
应用示例子元素的变动下面的例子说明如何读取变动记录。 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 option = {
'childList': true,
'subtree': true};
mo.observe(document.body, option);上面代码的观察器,观察<body>的所有下级节点(childList表示观察子节点,subtree表示观察后代节点)的变动。回调函数会在控制台显示所有变动的类型和目标节点。 属性的变动下面的例子说明如何追踪属性的变动。 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);上面代码先设定追踪属性变动('attributes': true),然后设定记录变动前的值。实际发生变动时,会将变动前的值显示在控制台。 取代 DOMContentLoaded 事件网页加载的时候,DOM 节点的生成会产生变动记录,因此只要观察 DOM 的变动,就能在第一时间触发相关事件,因此也就没有必要使用DOMContentLoaded事件。 var observer = new MutationObserver(callback);
observer.observe(document.documentElement, {
childList: true,
subtree: true
}
);上面代码中,监听document.documentElement(即HTML节点)的子节点的变动,subtree属性指定监听还包括后代节点。因此,任意一个网页元素一旦生成,就能立刻被监听到。 下面的代码,使用MutationObserver对象封装一个监听 DOM 生成的函数。 (function(win){
'use strict';
var listeners = [];
var doc = win.document;
var MutationObserver = win.MutationObserver || win.WebKitMutationObserver;
var observer;
function ready(selector, fn){
// 储存选择器和回调函数
listeners.push({
selector: selector,
fn: fn
});
if(!observer){
// 监听document变化
observer = new MutationObserver(check);
observer.observe(doc.documentElement, {
childList: true,
subtree: true
});
}
// 检查该节点是否已经在DOM中
check();
}
function check(){
// 检查是否匹配已储存的节点
for(var i = 0; i < listeners.length; i++){
var listener = listeners[i];
// 检查指定节点是否有匹配
var elements = doc.querySelectorAll(listener.selector);
for(var j = 0; j < elements.length; j++){
var element = elements[j];
// 确保回调函数只会对该元素调用一次
if(!element.ready){
element.ready = true;
// 对该节点调用回调函数
listener.fn.call(element, element);
}
}
}
}
// 对外暴露ready
win.ready = ready;
})(this);
ready('.foo',
function(element){
// ...
});在react中列子我们定义一个div,并利用mutionObserver对它监听 const observer = new MutationObserver((mutationList, observer) => {
// 这里利用策略模式对mutationList.type属性进行检查
const mapFn = {
attributes: (mutationList, observer) => {
// 属性改变时候 属性修改,删除,新增
},
childList: (mutationList, observer) => {
//子节点改变时候 修改,删除,新增
},
characterData: (mutationList, observer) => {
// 如果它是节点 节点上所有字符的变化
}
}
typeof mapFn[mutationList.type] === 'function' && mapFn[mutationList.type](mutationList, observer);
console.log('observer', mutationList, observer)
});
const observerOptions = {
childList: true, // 观察目标子节点的变化,是否有添加或者删除
attributes: true, // 观察属性变动
subtree: true, // 观察后代节点,默认为 false
};
const moDiv = useRef(null)
useEffect(() => {
// 监听DOM
observer.observe(moDiv.current, observerOptions)
return () => {
// 利用useEffect返回方法在组件销毁时候取消监听
observer.disconnect()
}
}, [])
...
return (
<div ref={moDiv} id='moDiv'>
<ul>
<li>11111</li>
<li>22222</li>
</ul>
</div>
)
... |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com