什么是重排与重绘,如何减少重排

一,浏览器解析渲染页面过程

 当浏览器获得一个 html 文件时,会 "自上而下" 加载,并在加载过程中进行解析渲染。

        1. 获取 HTML 文件并进行解析,生成 DOM 树;
        2. 解析 HTML 的同时也会解析 CSS,生成 CSSOM 树;
        3. 将 DOM 树和 CSSOM 树结合,生成渲染树 (Render Tree);
        4. 根据生成的渲染树,进行布局 (Layout) (重排),得到节点的几何信息(位置,大小);
        5. 根据渲染树以及重排得到的几何信息,进行绘制 (Painting) (重绘),调用 GPU (图形处理器) 将元素呈现出来。

二,重排(reflow)

重排也叫回流,当 DOM 的变化影响了元素的几何信息(位置、尺寸大小等),浏览器需要重新计算元素的几何属性,将其安放在界面的正确位置,这个过程叫做重排。

常见引起重排的属性和方法

  width: 
  height:
  margin: 
  padding: 
  display: 
  border-width: 
  border: 
  position: 
  overflow: 
  font-size: 
  vertical-align: 
  min-height: 
  clientWidth
  clientHeight
  clientTop
  clientLeft
  offsetWidth
  offsetHeight
  offsetTop
  offsetLeft
  scrollWidth
  scrollHeight
  scrollTop
  scrollLeft
  scrolllntoView()
  scrollTo()
  getComputedStyle()
  scrollIntoViewIfNeeded()
  getBoundingClientRect()

重排何时触发:

    1. 页面初始渲染,这是开销最大的一次重排,并且避免不了;
    2. 添加或删除可见的 DOM 元素;
    3. 元素的位置发生变化;
    4. 元素的尺寸发生变化(包括外边距、内边距、边框大小、高度和宽度等);
    5. 元素内容发生变化(例如文字数量、图片大小等);
    6. 元素字体大小改变;
    7. 改变浏览器窗口尺寸(例如 resize 事件发生时);
    8. 激活 CSS 伪类(例如 :hover);
    9. 设置 style 属性的值,因为通过设置 style 属性改变节点样式的话,每一次设置都会触发一次          重排;
   10.查询某些属性或调用某些计算方法:offsetWidth、offsetHeight 等,除此之外,当我们调用            getComputedStyle 方法,或者 IE 里的 currentStyle 时,也会触发重排,原理是一样的,都           为求一个 “即时性” 和 “准确性” 。

三,重绘(repaint)

当一个元素的外观发生变化,但没有改变布局,重新把元素外观绘制出来的过程,叫做重绘。

 常见引起重绘的属性和方法

  color: 
  box-shadow: 
  visibility: 
  border-style: 
  border-radius: 
  outline: 
  outline-style: 
  outline-width: 
  outline-color: 
  background: 
  background-image: 
  background-position: 
  background-repeat: 
  background-size: 

重绘何时触发:

    1. 颜色的改变;

    2. 文本方向的改变;

    3. 阴影的改变等。

 四,重排与重绘的关系

                重排一定导致重绘,重绘不一定导致重排。       

     1. 每个页面初始化渲染时至少触发一次重排和重绘。

     2. 重排和重绘的代价都很高昂,频繁重排重绘,会破坏用户体验,让页面显示变迟缓。

     3. 所以我们要尽可能避免频繁触发重排和重绘,尤其是重排。

 五,如何减少重排和重绘

1,浏览器对于重排和重绘的优化

浏览器会维护一个队列,把所有会引起重排、重绘的操作放入这个队列,等队列中的操作到了一定数量或者到了一定的时间间隔,浏览器就会 flush 队列,进行一个批处理。这样就会让多次的重排、重绘变成一次重排重绘。

但当你获取布局信息的操作的时候,例如 offsetTop 等方法,为了保证获取结果的准确性,就会打破浏览器的这种优化策略,强制浏览器提前 flush 队列。

2,css中避免重排重绘

        1. 减少重排范围,尽量将需要重排的内容固定在局部范围。

        2.不要使用 table 布局,可能很小的一个改动会造成整个 table 的重新布局。不得已使用                     table的场景,可以设置 table-layout: auto; 或者 table-layout: fixed; 这样可以让 table一行                一行的渲染,同时可可以限制重排的影响范围。
        3. 集中修改样式。这样可以尽可能利用浏览器的优化机制,一次重排重绘就完成渲染。
        4. 避免设置多项内联样式。
        5. 如果想设定元素的样式,可以通过改变元素的 class 类名(尽可能在 DOM 树的最里层)。
        6. 将 DOM 离线。通过设置元素属性 display: none; 将其从页面上去掉,然后再进行后续操                作,这些后续操作将不会出发重排重绘,最后通过 display 属性显示。另外,visibility:                    hidden 的元素只对重绘有影响,不影响重排。
        7. 使用 position: absolute / fixed; 脱离文档流。例如那些复杂的动画,对其设置 position:                    absolute / fixed; 尽可能地使元素脱离文档流,从而减少对其他元素的影响。
        8. 利用 transform translate 去代替 left top 的变换。
        9. 使用 css3 硬件加速,可以让 transform、opacity、filters 这些动画不会引起重排重绘。
       10. 避免使用 css 的 JavaScript 表达式。
       11.将频繁重排或重绘的节点设置为图层。将节点设置为 video 或 iframe;为节点添加 will-                  change 属性。

3,js中避免重排和重绘

        1. 减少直接操作 DOM 元素。不要一条一条地修改 DOM 的样式,改用 className 来控制。
        2. 分离读写操作。当需要 js 操作元素样式时,即将获取样式属性的操作集中执行,并缓存                  值,在需要设置样式属性时也集中处理,避免获取和设置的操作互相夹杂。因为获取、设              置的操作都会引起重排。
        3. 动态插入多个节点时,可以使用文档碎片(DocumnetFragment),创建后一次插入,避                免多次的渲染性能。DocumnetFragment 是一个保存多个元素的容器对象(保存在内                      存),当更新其中的一个或者多个元素时,页面不会更新。
        4. 不要把 DOM 节点的 offsetLeft 等属性值放在一个循环里当成循环里的变量。
        5. 使用 resize 事件时,做防抖和节流处理。

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值