我有一棵DOM节点树,并删除了几个子节点。我想确定DOM树的更新大小。
MutationObserver不起作用,因为它通知DOM模型更改,但是渲染尚未实际完成,因此大小尚未更新。
[有多种方法可以做到这一点(setTimeout(delay),或多个嵌套的requestAnimationFrame(),但是我不想在以后遇到意外的大小问题。
是否有任何非骇客的方式?
盒式布局的更新,也称为“重排”可以为triggered synchronously,不需要“完整渲染”。您可以在this answer中查看有关渲染操作同步性的更多详细信息。
因此,在您的情况下,您可以在进行DOM更新后直接获取元素的新大小,因为获取这种大小本身会触发重排;甚至没有必要使用MutationObserver。
const elem = document.getElementById('elem');
console.log('initial', elem.offsetHeight);
elem.querySelectorAll('p:not(.notme)').forEach(el=>el.remove());
// getting '.offsetHeight' triggers a reflow
console.log('after removing', elem.offsetHeight);
<div id="elem">
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p class="notme">Hello</p>
</div>
尽管请注意,触发重排在性能方面会付出一些代价,所以如果您担心其他事情之后还会修改DOM,则可能需要等待绘画事件循环迭代,使用requestAnimationFrame
在调用以下内容之一之前触发它的方法。
const elem = document.getElementById('elem');
console.log('initial', elem.offsetHeight);
elem.querySelectorAll('p:not(.notme)').forEach(el=>el.remove());
// wait the painting frame in case other operations also modify the DOM
requestAnimationFrame(()=> {
console.log('after removing', elem.offsetHeight);
});
<div id="elem">
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
<p class="notme">Hello</p>
</div>
Ps:对于仍然对这个XY问题的Y感兴趣的人,您可以看看this Q/A,它演示了即将推出的requestPostAnimationFrame
的用法并为此提供了一个猴子补丁。