场景
2024年04月17日
一、监听动态DOM元素
描述: 有一盒子容器 box
, 里面的子元素需要请求获取 , 需要获取之后重新设置 box
的高度。那么这时候可以使用 MutationObserver
观察 box
及其子元素
实现
- Html
- Css
- JavaScript
<div id="box"></div>
const box = document.querySelector("div[id='box']");
console.log("box 的高度为: ", box.clientHeight);
function createBoxChild() {
const child = document.createElement("div");
child.style.width = "100px";
child.style.height = "100px";
child.style.backgroundColor = "red";
box.append(child);
}
function mutationObserverCallback(mutationList, observer) {
mutationList.forEach((mutation) => {
switch (mutation.type) {
case "subtree":
console.log(mutation);
break;
case "childList":
console.log("box 的高度为: ", box.clientHeight);
observer.disconnect();
break;
case "attributes":
console.log(mutation);
break;
case "characterData":
console.log(mutation);
break;
default:
console.log(mutation);
}
});
}
const mutationObserver = new MutationObserver(mutationObserverCallback);
mutationObserver.observe(box, {
subtree: true,
childList: true,
attributes: true,
characterData: true,
attributeFilter: ["width", "height"],
});
setTimeout(() => {
createBoxChild();
}, 3000);
二、Vue 异步更新队列
描述: 创建一个 MutationObserver
对象, 并且把 flushCallbacks
作为 MutationObserver
构造函数的回调函数。之后我们创建一个文本节点, 通过 mutationObserver.observe()
来监听该文本节点, 如果文本节点的内容有任何变动的话, 它就会触发 flushCallbacks
回调函数。因此, 我们只需要 timerFunc
函数中, 修改文本内容, 文本节点内容发生变化之后, 进而触发 MutationObserver
的回调。
实现
let timerFunc;
const callbacks = [];
function flushCallbacks() {
const copies = callbacks.slice();
callbacks.length = 0;
for (let i = 0; i < copies.length; i++) {
copies[i]();
}
}
function buildTimerFunc() {
let counter = 1;
const mutationObserver = new MutationObserver(flushCallbacks);
const textNode = document.createTextNode(String(counter));
mutationObserver.observe(textNode, {
characterData: true,
});
timerFunc = () => {
counter = (counter + 1) % 2;
textNode.data = String(counter);
};
}
function nextTick(callback, context) {
callbacks.push(() => {
if (callback) {
try {
callback.call(context);
} catch (error) {
console.log("Error");
}
}
});
timerFunc();
}
function task1() {
console.log("task1");
}
function task2() {
console.log("task2");
}
buildTimerFunc();
nextTick(task1);
nextTick(task2);