性能优化中,减小重绘重排应该是一种很好的优化方式,咱们具体看一下什么状况下会形成重绘重排,为何减小重绘重排能够作到优化,怎么样减小重绘重排。css
咱们先看看当浏览器拿到服务端返回的资源时,是如何渲染的。html
首先浏览器会进行文件解析,主要解析三个东西:jquery
解析完成以后api
布局完成以后,就要进行绘制了,将各层发给 GPU,GPU 将各层合成,显示在屏幕上,即 composite。浏览器
当咱们开始绘制的时候,若是使用 js 操做了 dom 元素,或者改变了 css 属性,就可能会形成重绘(repaint)和重排(reflow)。性能优化
repaint:屏幕的一部分进行了重画,好比某个 css 中改变背景色,元素尺寸没有变。 reflow:任何一个元素的尺寸发生了变化,须要从新验证并计算 render tree,就会形成重排。app
在 PC 时代,咱们用 jquery 进行获取元素,改变元素的尺寸,及时发生重排,咱们也很难感知到,可是当移动时代到来以后,若是频繁发生重排,那手机就会受不了了。dom
尤为是在执行下面操做时,成本会很高:svg
若是发生上述的行为基本都会形成重绘和重排。工具
当发生重排时,必定会发生重绘,可是发生重绘不必定会发生重排。
浏览器中每一个元素节点都有 reflow 方法,当一个元素发生 reflow 时,他的子节点都会发生 reflow。
举几个例子来讲明一下形成重绘重排的状况:
var bodyStyle = document.body.style; // cache
bodyStyle.padding = '20px'; // reflow, repaint
bodyStyle.border = '10px solid red'; // 再一次的 reflow 和 repaint
bodyStyle.color = 'blue'; // repaint
bodyStyle.backgroundColor = '#fad'; // repaint
bodyStyle.fontSize = '2em'; // reflow, repaint
// new DOM element - reflow, repaint
document.body.appendChild(document.createTextNode('children!'));
复制代码
前面说了浏览器的渲染机制,多一次重绘就须要浏览器从新进行一次绘制,及时 GPU 处理会比较快,可是也是吃不消的,更别说重排了,重排一个 dom,会从新生成 render Tree,而后从新绘制。
其实浏览器很聪明,不可能每次修改样式就 reflow 或者 repaint 一次,通常来讲,浏览器会积累一批操做,而后作一次 reflow。
可是也有些例外状况,好比 resize 窗口,改变窗口字体,浏览器会当即进行 reflow。
虽然浏览器会这么作,可是咱们也应该减小重绘重排的次数,在开发阶段就为浏览器进行特殊的关爱,毕竟是天天陪伴咱们的小伙伴。
下面总结了一些针对 reflow 和 repaint 的最佳实践:
当每次布局完成以后,就会发生 composite 过程,浏览器都把重绘后的图像发给 GPU 去合成并显示。
在上面最佳实践中最后提到了动画,动画实际上是比较耗费性能的,由于动画的每一帧都会发给 GPU 去合成,重绘重排会发生在动画的每一帧。
咱们在写动画的时候,能够经过 js 写,也能够经过 css 写。两种方式在写动画时,过程也是不同的。
因此不难看出,耗费性能最少并能并最流畅的动画是只触发合成。
为了仅发生 composite,咱们作动画的 css property 必须知足如下三个条件:
知足以上以上条件的 css property 只有 transform 和 opacity。
这样的话,因为没有重排和重绘,只有合成,那么浏览器在动画执行以前就知道动画如何开始和结束。
而且有两个优点:
事实上影响动画流畅性的因素不止重排重绘,还有 CPU 内存。
css 动画有一个重要的特性,它是彻底工做在 GPU 上。由于你声明了一个动画如何开始和如何结束,浏览器会在动画开始前准备好全部须要的指令;并把它们发送给 GPU。
而若是使用 js 动画,浏览器必须计算每一帧的状态;为了保证平滑的动画,咱们必须在浏览器主线程计算新状态;把它们发送给 GPU 至少 60 次每秒。
除了计算和发送数据比 css 动画要慢,主线程的负载也会影响动画; 当主线程的计算任务过多时,会形成动画的延迟、卡顿。
因此最佳实践中最后一条就提到了,在写动画时,尽可能写 css 动画,而且尽可能用 transform 和 opacity。
谷歌浏览器检测重绘工具:右上角...,more tools,rendering。
勾选了 paint flashing 时,在刷新页面以后,就会发现有有绿色的背景,有绿色的背景就表明着重排。
还能够勾选 FPS meter,能够查看渲染页面时候 GPU 的使用率。
方便发现本身在开发过程当中,哪些操做形成了重绘重排,尽可能减小修改次数,优化性能。