什么是浏览器重绘和重排?

在浏览器渲染页面后,任何导致元素视觉变化或几何位置变化的操作,都会触发浏览器的重新渲染流程。这个过程主要涉及两个核心概念:重排和重绘。理解它们的区别和触发条件,对于编写高性能的前端代码至关重要。

重排:布局的重新计算

重排,也叫回流,是指浏览器需要重新计算元素在文档中的几何属性(位置和大小),并更新整个渲染树的过程。这会导致后续的重绘。任何会改变元素布局的操作都会触发重排。

const element = document.getElementById('myDiv');
// 以下操作都会触发重排
element.style.width = '100px';
element.style.height = '50px';
element.style.margin = '10px';
// 获取某些布局属性也会强制触发同步重排,以获取最新值
const width = element.offsetWidth; // 这会强制刷新队列

常见触发重排的操作包括:添加或删除可见的DOM元素、元素尺寸改变(边距、填充、边框、宽高)、内容变化(文字数量、图片大小)、页面初次渲染、浏览器窗口尺寸变化、以及读取某些布局属性(如offsetTopscrollTopgetComputedStyle等)。

重绘:像素的重新填充

重绘发生在元素的外观发生改变,但没有影响其布局的时候。浏览器会重新绘制受影响元素的像素到屏幕上。重排一定会导致重绘,但重绘不一定需要重排。

element.style.color = 'red';
element.style.backgroundColor = '#ccc';
element.style.outline = '1px solid blue';

改变颜色、背景、边框样式、可见性等属性,只会触发重绘,因为元素的几何尺寸和位置没有变化。

性能影响与优化策略

重排的成本比重绘高得多,因为它涉及整个渲染树的重新计算,可能引发连锁反应。频繁的重排/重绘是导致页面卡顿和响应缓慢的主因。

// 不佳的做法:多次读写分离,触发多次重排
div.style.left = '10px';
const width = div.offsetWidth; // 读,触发重排
div.style.top = '20px';
const height = div.offsetHeight; // 读,再次触发重排

// 优化:使用 fastdom 模式,批量读写
div.style.left = '10px';
div.style.top = '20px';
// 将读取操作集中到后面
const width = div.offsetWidth;
const height = div.offsetHeight;

现代浏览器会将多次重排操作排队,并批量执行。但是,如果在一次重排后立即读取布局属性,浏览器会强制刷新队列以提供最新值,这会导致意外的性能损耗。因此,最佳实践是将读取操作集中,与写入操作分开。

此外,使用CSS的transformopacity属性来实现动画是高效的选择,因为它们可以由合成器线程直接处理,通常不会触发主线程的重排和重绘。对于复杂的DOM操作,可以先将元素脱离文档流(如设置display: none),操作完成后再放回,这样只会触发两次重排。

理解重排和重绘的机制,能让你在编写动态网页时做出明智的决策,避免不必要的布局计算,从而确保流畅的用户体验。

© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容