重绘(reflows)与重排(repaints)(《高性能JavaScript》随笔(二))

一、重排何时发生?

简而言之,当页面布局和几何属性发生变化时就需要“重排”

  • 添加/删除可见的DOM元素
  • 元素位置改变
  • 元素尺寸改变(包括:margin、padding、border等属性)
  • 内容改变,比如:文本改变,或被另一个不同尺寸的图片替代了。
  • 页面渲染初始化
  • 浏览器窗口尺寸改变

二、渲染树变化的排队与刷新

浏览器每次重排都会产生计算消耗,大多数浏览器通过队列化修改并批量执行(即浏览器会判断元素样式是否发生改变(重绘或重排),如果发生就放到渲染队列里,直到没有样式发生改变,再进行渲染,即只有一次渲染过程)。

但是,如果你中途使用了获取布局信息的操作,会导致队列强制刷新,如:

  • offsetTop、offsetLeft、offsetWidth、offsetHeight
  • scrollTop、scrollLeft、scrollWidth、scrollHeight
  • clientTop、clientLeft、clientWidth、clientHeight
  • getComputedStyle()

以上属性与方法需要返回最新的布局信息,所以浏览器会强制执行队列里的“待处理变化”。所以,在修改样式的过程中,最可能避免使用上面列出的属性。即使你在获得最近未发生改变的或与最新改变无关的布局信息,浏览器也会强制刷新,所以应该尽可能减少使用以上的属性和方法的次数,或将值赋给局部变量。

三、最小化重绘和重排

  • 改变样式,使用cssText完成全部样式样式修改,但目前多数浏览器已经对此进行优化
  • 批量修改DOM

当需要对DOM元素进行一系列操作的时候(不只是样式修改,比如对dom元素增加删除),可以通过以下步骤减少重绘和重排的次数:

1. 使元素脱离文档流

2. 对其应用多重变化

3. 把元素带回文档中

注意,此时整个过程中,只触发了两次重排,分别是1和3。也就是说2步骤里面发生几次变化,到渲染的时候,只有两次重排。以此提出三个基本方法:

1. 隐藏元素,修改,重新显示

2. 使用文档片断(document fragment)在当前DOM之外建立一个子树,再完成修改后拷贝回文档中。

3. 将原始元素拷贝到一个脱离文档的节点中,修改副本,完成后再替换原始元素

 四、让元素脱离文档流

一般来说,重排只影响渲染树中的一小部分,但也可能影响很大的部分,甚至影响整个渲染树。渲染树中需要重新计算的节点越多,情况就越糟糕。以下步骤可以避免页面大区域重排

1. 使用绝对定位定位页面动画元素,将其脱离文档流

2. 让元素动起来。当它扩大时,会临时覆盖部分分页面。但这只是页面一个小区域的重绘过程,不会产生重排并重绘页面的大部分内容

3. 当动画结束时恢复定位,从而只会下移一次文档的其他元素

内容参考《高性能JavaScript》——丁琛 译

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值