重排与重绘

栏目: CSS · 发布时间: 5年前

内容简介:原文地址:在页面的生命周期中,一些效果的交互都有可能发生重排(

原文地址: http://www.cun-xu.cn/index.php/2018/12/25/重排与重绘/

在页面的生命周期中,一些效果的交互都有可能发生重排( Layout )和重绘( Painting ),这些都会使我们付出高额的性能代价。 浏览器从下载文件至本地到显示页面是个复杂的过程,这里包含了重绘和重排。通常来说,渲染引擎会解析HTML文档来构建DOM树,与此同时,渲染引擎也会用CSS解析器解析CSS文档构建CSSOM树。接下来,DOM树和CSSOM树关联起来构成渲染树( RenderTree ),这一过程称为 Attachment 。然后浏览器按照渲染树进行布局( Layout ),最后一步通过绘制显示出整个页面。

重排与重绘

其中重排和重绘是最耗时的部分,一旦触发重排,我们对DOM的修改引发了DOM几何元素的变化,渲染树需要重新计算, 而重绘只会改变 vidibilityoutline 、背景色等属性导致样式的变化,使浏览器需要根据新的属性进行绘制。更比而言,重排会产生比重绘更大的开销。所以,我们在实际生产中要严格注意减少重排的触发。

触发重排的操作主要是几何因素:

1.页面第一次渲染 在页面发生首次渲染的时候,所有组件都要进行首次布局,这是开销最大的一次重排。 2.浏览器窗口尺寸改变 3.元素位置和尺寸发生改变的时候 4.新增和删除可见元素 5.内容发生改变(文字数量或图片大小等等) 6.元素字体大小变化。 7.激活CSS伪类(例如: :hover )。 8.设置style属性 9.查询某些属性或调用某些方法。比如说:

offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight

除此之外,当我们调用 getComputedStyle 方法,或者IE里的 currentStyle 时,也会触发重排,原理是一样的,都为求一个“即时性”和“准确性”。

触发重绘的操作主要有:

vidibilityoutline 、背景色等属性的改变

我们应当注意的是: 重绘不一定导致重排,但重排一定会导致重绘。

那么我们可以采取哪些措施来避免或减少重排带来的巨大开销呢?

1.分离读写操作

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 并没有触发重排,仅仅拿值而已。

2.样式集中改变

通过 classcssText 进行集中改变样式 未进行优化的代码是这样的:

//bad
var left = 10;
var top = 10;
el.style.left = left + "px";
el.style.top = top + "px";

虽然现在大部分现代浏览器都会有 Flush 队列进行渲染队列优化,但是有些老版本的浏览器比如IE6这样的坑货效率依然低下: 这时我们就可以通过上面所说的利用 classcssText 属性集中改变样式

//good
el.className += " className";
//or
el.style.cssText += "; left: " + left + "px; top: " + top + "px;";

3. 缓存布局信息

// 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';
复制代码

4. 将DOM离线

  • DOM离线化

一旦我们给元素设置 display:none 时,元素不会存在于渲染树中,相当于将其从页面“拿掉”,我们之后的操作将不会触发重排和重绘,这叫做DOM的离线化。

dom.display = 'none'
// 修改dom样式
dom.display = 'block'
复制代码
  • 通过使用 DocumentFragment 创建一个 dom 碎片,在它上面批量操作 dom ,操作完成之后,再添加到文档中,这样只会触发一次重排。

  • 复制节点,在副本上工作,然后替换它!

5. 将 position 属性设置为 absolutefixed

position 属性为 absolutefixed 的元素,重排开销比较小,不用考虑它对其他元素的影响

6. 优化动画

  • 可以把动画效果应用到 position 属性为 absolutefixed 的元素上,这样对其他元素影响较小

动画效果还应牺牲一些平滑,来换取速度,这中间的度自己衡量:

比如实现一个动画,以1个像素为单位移动这样最平滑,但是 Layout 就会过于频繁,大量消耗CPU资源,如果以3个像素为单位移动则会好很多。

  • 启用GPU加速

GPU 硬件加速是指应用 GPU 的图形性能对浏览器中的一些图形操作交给 GPU 来完成,因为 GPU 是专门为处理图形而设计,所以它在速度和能耗上更有效率。

GPU 加速通常包括以下几个部分:Canvas2D,布局合成, CSS3转换( transition s),CSS3 3D变换( transforms ),WebGL和视频( video )。

/*
* 根据上面的结论
* 将 2d transform 换成 3d
* 就可以强制开启 GPU 加速
* 提高动画性能
*/
div {
transform: translate3d(10px, 10px, 0);
}

娘滴,终于写完了,肩膀子疼的我,得要得肩周炎了。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

运营实战指南

运营实战指南

韩利 / 电子工业出版社 / 2016-9-1 / 49

《运营实战指南》架构清晰,前8章主要通过故事形式深入浅出理解运营,将运营基础知识和概念融入到故事中。第9章讲解运营核心方法论,从目标、关键驱动元素、试错调优、高效运行4部分来完整讲解一个运营项目从0到1的过程。第10章、11章、12章深入讲解了运营人拿业绩最核心的知识点:用户、内容和文案。其中数据分析、活动运营等内容以案例形式穿插在各个章节中。最后两章,主谈运营人在日常生活中如何历练以及一个运营人......一起来看看 《运营实战指南》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具