重绘与重排

重绘与重排(Reflow and Repaint)

一篇写的很好的对于了解重绘与重排的文章:

https://dev.to/gopal1996/understanding-reflow-and-repaint-in-the-browser-1jbg

基本概念

重排

发生在浏览器重新计算网页的某些部分的位置和几何形状时(更改会影响部分或整个页面的布局),重排会导致DOM中所有子元素和祖先元素重排。这通常会紧接着重绘(repaint),即浏览器重新绘制网页以显示更新后的视觉效果。

重绘

浏览器重新绘制网页以显示由 UI 更改引起的视觉更新且不会影响元素布局时发生(例如:可见性、背景颜色、轮廓等),这通常是在重排之后发生的,重排是浏览器重新计算网页的某些部分的位置和几何形状。

总结

重排与重绘都是非常消耗性能的操作,大多数重排都会导致页面的重新渲染,是导致DOM脚本(Script)加载速度慢的主要原因之一,尤其是在低性能设备上。

什么会导致重绘与重排

  1. 添加、删除、更新DOM节点发生重排
  2. display:none隐藏DOM元素:会导致重排和重绘
  3. visibility:hidden隐藏DOM元素:只会导致重绘,因为没有布局或位置变化
  4. 移动DOM节点, 为DOM节点设置动画:触发重排和重绘
  5. 调整窗口大小:触发重排
  6. 更改字体样式会改变元素的几何形状。这意味着它可能会影响页面上其他元素的位置或大小,这两者都需要浏览器执行重排。一旦这些布局操作完成,任何已经修改的像素都需要重绘,即会触发重排与重绘
  7. 添加或删除样式表将导致重排/重绘
var bodyStyle = document.body.style; // cache

bodyStyle.padding = "20px"; // reflow, repaint
bodyStyle.border = "10px solid red"; // reflow, repaint

bodyStyle.color = "blue"; // repaint only, no dimensions changed
bstyle.backgroundColor = "#cc0000"; // repaint

bodyStyle.fontSize = "2em"; // reflow, repaint

// new DOM element - reflow, repaint
document.body.appendChild(document.createTextNode('Hello!'));

操作DOM的脚本(Script)是昂贵的操作,因为每次修改文档或文档的一部分时,它们都会重新计算。正如我们从引发重排的许多事情中看到的那样,它每秒可以发生成千上万次

减少重排/重绘

减少重排/重绘对用户体验的负面影响的策略是简单地减少重排和重绘,减少对样式信息的请求,这样浏览器就可以优化重排。那么该如何实现?

  1. 不要一个接一个地改变CSS样式。为了保持可维护性,最好更改类名,而不是样式。如果样式是动态的,可以编辑CSSText属性
// bad
var left = 10,
    top = 10;
el.style.left = left + "px";
el.style.top  = top  + "px";

// better 
el.className += " theclassname";

// or when top and left are calculated dynamically...

// better
el.style.cssText += "; left: " + left + "px; top: " + top + "px;";
  1. 批量DOM更改
  • 使用documentFragment保存临时更改
  • 克隆、更新、替换节点
  • 使用display:none隐藏元素(1次重排,1次重绘),然后再添加100个更改,然后再恢复显示(共2次重排,2次重绘)
  1. 不要反复请求计算样式,将它们缓存到变量中
  • 多次读/写(如元素的height属性)
  • 多次从DOM写入,然后读取,导致文档重排
  • 读取(缓存)、写入(使布局无效)、读取(触发布局)。
  • 解决:先读所有内容,然后再写所有内容

性能差的代码:

var box1Height = document.getElementById('box1').clientHeight;
document.getElementById('box1').style.height = box1Height + 10 + 'px';

var box2Height = document.getElementById('box2').clientHeight;
document.getElementById('box2').style.height = box2Height + 10 + 'px';

var box3Height = document.getElementById('box3').clientHeight;
document.getElementById('box3').style.height = box3Height + 10 + 'px';

var box4Height = document.getElementById('box4').clientHeight;
document.getElementById('box4').style.height = box4Height + 10 + 'px';

var box5Height = document.getElementById('box5').clientHeight;
document.getElementById('box5').style.height = box5Height + 10 + 'px';

var box6Height = document.getElementById('box6').clientHeight;
document.getElementById('box6').style.height = box6Height + 10 + 'px';

performance monitor for bad code

优化的代码:

var box1Height = document.getElementById('box1').clientHeight;
var box2Height = document.getElementById('box2').clientHeight;
var box3Height = document.getElementById('box3').clientHeight;
var box4Height = document.getElementById('box4').clientHeight;
var box5Height = document.getElementById('box5').clientHeight;
var box6Height = document.getElementById('box6').clientHeight;

document.getElementById('box1').style.height = box1Height + 10 + 'px';
document.getElementById('box2').style.height = box2Height + 10 + 'px';
document.getElementById('box3').style.height = box3Height + 10 + 'px';
document.getElementById('box4').style.height = box4Height + 10 + 'px';
document.getElementById('box5').style.height = box5Height + 10 + 'px';
document.getElementById('box6').style.height = box6Height + 10 + 'px';

performance monitor for optimized code

原因:通过批量更改DOM,减少重排操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白帆白女士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值