浏览器重绘与回流触发时机探究及DOM操作案例疑问
我希望深入了解浏览器中DOM操作时的具体行为,目前关于浏览器何时执行重绘(repaint)和回流(reflow)的资料较少,已有文献多聚焦于二者定义,对触发时机涉及不多。
具体而言,我对如下代码存在疑问:
function clickHandler() { domElement1.textContent = 'Hello'; domElement2.textContent = 'World'; }
假设变量domElement1和domElement2分别存储两个DOM元素,clickHandler函数绑定在按钮上,点击按钮时会更新这两个元素的内容。
问题在于:此操作是否可能引发两次重绘?即浏览器先更新domElement1并完成重绘/回流等屏幕更新,之后再更新domElement2并触发另一轮重绘/回流?还是浏览器会确保按钮事件处理函数完全执行完毕后,才对实际DOM进行修改?
我猜测浏览器会尝试维持每秒60帧的刷新率,理论上这两次修改可能处于不同帧中,该猜测是否正确?
解答
不会触发两次重绘或回流,你的猜测也不成立。
浏览器的事件循环机制决定了:在当前宏任务(这里就是按钮点击的事件处理函数)执行完毕前,不会进行任何页面渲染操作。也就是说,你在clickHandler里连续修改两个元素的文本内容,浏览器会把这两次DOM变更都暂存起来,等整个函数执行完,才会统一计算一次回流(如果元素布局受影响的话),然后触发一次重绘。
原因很简单:如果每一次DOM操作都立刻触发回流/重绘,会导致页面性能急剧下降——频繁的渲染计算会占用大量主线程资源,让页面变得卡顿。浏览器会自动做这种批量优化,把同一宏任务里的所有DOM修改合并,一次性处理渲染。
至于60帧的刷新率,只有当某个宏任务的执行时间超过单帧的时间(约16.6ms)时,才会导致丢帧。但修改两个元素的文本内容是非常轻量的操作,肯定能在单帧时间内完成,所以根本不会出现“两次修改分属不同帧”的情况。
内容的提问来源于stack exchange,提问作者Daniel Rotter

