重排与重绘

栏目: 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);
}

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


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

查看所有标签

猜你喜欢:

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

Web Development Recipes

Web Development Recipes

Brian P. Hogan、Chris Warren、Mike Weber、Chris Johnson、Aaron Godin / Pragmatic Bookshelf / 2012-1-22 / USD 35.00

You'll see a full spectrum of cutting-edge web development techniques, from UI and eye candy recipes to solutions for data analysis, testing, and web hosting. Make buttons and content stand out with s......一起来看看 《Web Development Recipes》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具