我有一棵DOM节点树,并删除了几个子节点。 我想确定DOM树的更新大小。
MutationObserver无法工作,因为它会通知DOM模型更改,但是渲染实际上尚未完成,因此大小尚未更新。
有多种方法可以做到这一点(setTimeout(delay)或多个嵌套的requestAnimationFrame()),但是我不想在以后遇到意外的大小调整问题。
是否有任何非骇客的方式?
答案 0 :(得分:1)
对盒式布局的更新(也称为“重排”)可以为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
的用法,并为此提供了一个猴子补丁。