如何等待 DOM 更改渲染?(突变观察者不起作用)



我有一个DOM节点树,并删除了一些子节点。 我想确定 DOM 树的更新大小。

MutationObserver 不起作用,因为它会通知 DOM 模型更改,但渲染尚未实际完成,因此大小尚未更新。

有一些黑客方法可以做到这一点(setTimeout(delay(,或多个嵌套的请求AnimationFrame(((,但我不想在以后遇到意外的大小问题。

有没有非黑客的方法可以做到这一点?

框布局的更新,即"回流"可以同步触发,并且不需要"完整渲染"。 有关渲染操作同步性的更多详细信息,您可以查看此答案。

所以在你的例子中,你可以在完成 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感兴趣的人,你可以看看这个问答,它演示了即将到来的requestPostAnimationFrame的使用,并为它提供了一个猴子补丁。

最新更新