原文地址:http://www.cun-xu.cn/index.ph...php
在页面的生命周期中,一些效果的交互都有可能发生重排(Layout
)和重绘(Painting
),这些都会使咱们付出高额的性能代价。
浏览器从下载文件至本地到显示页面是个复杂的过程,这里包含了重绘和重排。一般来讲,渲染引擎会解析HTML文档来构建DOM树,与此同时,渲染引擎也会用CSS解析器解析CSS文档构建CSSOM树。接下来,DOM树和CSSOM树关联起来构成渲染树(RenderTree
),这一过程称为Attachment
。而后浏览器按照渲染树进行布局(Layout
),最后一步经过绘制显示出整个页面。css
其中重排和重绘是最耗时的部分,一旦触发重排,咱们对DOM的修改引起了DOM几何元素的变化,渲染树须要从新计算,
而重绘只会改变vidibility
、outline
、背景色等属性致使样式的变化,使浏览器须要根据新的属性进行绘制。更比而言,重排会产生比重绘更大的开销。因此,咱们在实际生产中要严格注意减小重排的触发。浏览器
1.页面第一次渲染
在页面发生首次渲染的时候,全部组件都要进行首次布局,这是开销最大的一次重排。
2.浏览器窗口尺寸改变
3.元素位置和尺寸发生改变的时候
4.新增和删除可见元素
5.内容发生改变(文字数量或图片大小等等)
6.元素字体大小变化。
7.激活CSS伪类(例如::hover
)。
8.设置style属性
9.查询某些属性或调用某些方法。好比说:缓存
offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeightdom
除此以外,当咱们调用getComputedStyle
方法,或者IE里的currentStyle
时,也会触发重排,原理是同样的,都为求一个“即时性”和“准确性”。ide
vidibility
、outline
、背景色等属性的改变布局
咱们应当注意的是:重绘不必定致使重排,但重排必定会致使重绘。性能
div.style.top = "10px"; div.style.bottom = "10px"; div.style.right = "10px"; div.style.left = "10px"; console.log(div.offsetWidth); console.log(div.offseHeight); console.log(div.offsetRight); console.log(div.offsetLeft);
原来的操做会致使四次重排和四次重绘,变换顺序以后只会触发一次重排
在第一个console
的时候,浏览器把以前上面四个写操做的渲染队列都给清空了。由于渲染队列原本就是空的,因此剩下的console
并无触发重排,仅仅拿值而已。字体
经过class
和cssText
进行集中改变样式
未进行优化的代码是这样的:优化
//bad var left = 10; var top = 10; el.style.left = left + "px"; el.style.top = top + "px";
虽然如今大部分现代浏览器都会有Flush
队列进行渲染队列优化,可是有些老版本的浏览器好比IE6这样的坑货效率依然低下:
这时咱们就能够经过上面所说的利用class
和cssText
属性集中改变样式
//good el.className += " className"; //or el.style.cssText += "; left: " + left + "px; top: " + top + "px;";
// bad 强制刷新 触发两次重排 div.style.left = div.offsetLeft + 1 + 'px'; div.style.top = div.offsetTop + 1 + 'px'; // good 缓存布局信息 至关于读写分离 var curLeft = div.offsetLeft; var curTop = div.offsetTop; div.style.left = curLeft + 1 + 'px'; div.style.top = curTop + 1 + 'px'; 复制代码
一旦咱们给元素设置display:none
时,元素不会存在于渲染树中,至关于将其从页面“拿掉”,咱们以后的操做将不会触发重排和重绘,这叫作DOM的离线化。
dom.display = 'none' // 修改dom样式 dom.display = 'block' 复制代码
dom
碎片,在它上面批量操做dom
,操做完成以后,再添加到文档中,这样只会触发一次重排。position
属性设置为absolute
或fixed
position
属性为absolute
或fixed
的元素,重排开销比较小,不用考虑它对其余元素的影响
position
属性为absolute
或fixed
的元素上,这样对其余元素影响较小动画效果还应牺牲一些平滑,来换取速度,这中间的度本身衡量:
好比实现一个动画,以1个像素为单位移动这样最平滑,可是Layout
就会过于频繁,大量消耗CPU资源,若是以3个像素为单位移动则会好不少。
GPU 硬件加速是指应用 GPU 的图形性能对浏览器中的一些图形操做交给 GPU 来完成,由于 GPU 是专门为处理图形而设计,因此它在速度和能耗上更有效率。
GPU 加速一般包括如下几个部分:Canvas2D,布局合成, CSS3转换(transition
s),CSS3 3D变换(transforms
),WebGL和视频(video
)。
/* * 根据上面的结论 * 将 2d transform 换成 3d * 就能够强制开启 GPU 加速 * 提升动画性能 */ div { transform: translate3d(10px, 10px, 0); }
娘滴,终于写完了,肩膀子疼的我,得要得肩周炎了。