摘要:原文地址在页面的生命周期中,一些效果的交互都有可能发生重排和重绘,这些都会使我们付出高额的性能代价。更比而言,重排会产生比重绘更大的开销。触发重绘的操作主要有背景色等属性的改变我们应当注意的是重绘不一定导致重排,但重排一定会导致重绘。
原文地址:http://www.cun-xu.cn/index.ph...
在页面的生命周期中,一些效果的交互都有可能发生重排(Layout)和重绘(Painting),这些都会使我们付出高额的性能代价。
浏览器从下载文件至本地到显示页面是个复杂的过程,这里包含了重绘和重排。通常来说,渲染引擎会解析HTML文档来构建DOM树,与此同时,渲染引擎也会用CSS解析器解析CSS文档构建CSSOM树。接下来,DOM树和CSSOM树关联起来构成渲染树(RenderTree),这一过程称为Attachment。然后浏览器按照渲染树进行布局(Layout),最后一步通过绘制显示出整个页面。
其中重排和重绘是最耗时的部分,一旦触发重排,我们对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、clientHeight
除此之外,当我们调用getComputedStyle方法,或者IE里的currentStyle时,也会触发重排,原理是一样的,都为求一个“即时性”和“准确性”。
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"; 复制代码
DOM离线化
一旦我们给元素设置display:none时,元素不会存在于渲染树中,相当于将其从页面“拿掉”,我们之后的操作将不会触发重排和重绘,这叫做DOM的离线化。
dom.display = "none" // 修改dom样式 dom.display = "block" 复制代码
通过使用DocumentFragment创建一个dom碎片,在它上面批量操作dom,操作完成之后,再添加到文档中,这样只会触发一次重排。
复制节点,在副本上工作,然后替换它!
position属性为absolute或fixed的元素,重排开销比较小,不用考虑它对其他元素的影响
可以把动画效果应用到position属性为absolute或fixed的元素上,这样对其他元素影响较小
动画效果还应牺牲一些平滑,来换取速度,这中间的度自己衡量:
比如实现一个动画,以1个像素为单位移动这样最平滑,但是Layout就会过于频繁,大量消耗CPU资源,如果以3个像素为单位移动则会好很多。
启用GPU加速
GPU 硬件加速是指应用 GPU 的图形性能对浏览器中的一些图形操作交给 GPU 来完成,因为 GPU 是专门为处理图形而设计,所以它在速度和能耗上更有效率。
GPU 加速通常包括以下几个部分:Canvas2D,布局合成, CSS3转换(transitions),CSS3 3D变换(transforms),WebGL和视频(video)。
/* * 根据上面的结论 * 将 2d transform 换成 3d * 就可以强制开启 GPU 加速 * 提高动画性能 */ div { transform: translate3d(10px, 10px, 0); }
娘滴,终于写完了,肩膀子疼的我,得要得肩周炎了。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/62059.html
摘要:完成重排后,浏览器会重新绘制受到影响的部分到屏幕中,该过程称为重绘重绘和重排操作都是代价昂贵的操作,它们会导致应用程序的反应迟钝,所以应该尽可能减少这类过程的发生。 浏览器下载完页面中的所有内容:HTML、JavaScript、CSS、图片——之后会解析并生成两个内部数据结构: DOM树:表示页面结构 渲染树:表示DOM节点如何显示 DOM树中的每一个需要显示的节点在渲染树中至少存...
摘要:完成重排后,浏览器会重新绘制受到影响的部分到屏幕中,该过程称为重绘重绘和重排操作都是代价昂贵的操作,它们会导致应用程序的反应迟钝,所以应该尽可能减少这类过程的发生。 浏览器下载完页面中的所有内容:HTML、JavaScript、CSS、图片——之后会解析并生成两个内部数据结构: DOM树:表示页面结构 渲染树:表示DOM节点如何显示 DOM树中的每一个需要显示的节点在渲染树中至少存...
摘要:完成重排后,浏览器会重新绘制受到影响的部分到屏幕中,该过程称为重绘重绘和重排操作都是代价昂贵的操作,它们会导致应用程序的反应迟钝,所以应该尽可能减少这类过程的发生。 浏览器下载完页面中的所有内容:HTML、JavaScript、CSS、图片——之后会解析并生成两个内部数据结构: DOM树:表示页面结构 渲染树:表示DOM节点如何显示 DOM树中的每一个需要显示的节点在渲染树中至少存...
摘要:回流也被称为重排,其实从字面上来看,重排更容易让人形象易懂即重新排版整个页面。重绘当页面元素样式改变不影响元素在文档流中的位置时如,,,浏览器只会将新样式赋予元素并进行重新绘制操作。你真的了解回流和重绘吗 简单先了解一下浏览器的渲染过程(图片来自于网络) showImg(https://segmentfault.com/img/bVbaC2e?w=624&h=289); 浏览器生成渲染...
摘要:,当元素插入后仍然保留对元素的指针。能够获得事件处理函数,而生成的新无法获得原先设置的事件处理函数。某些情况下,更加快速。无疑,在大多数情况下,更为快速且更加易用,但是使用的时候小心上述的那个问题就好。 WilsonLius blog 首发地址两者生成dom的方式有什么优劣呢?首先让我们看一个小问题再引入正题~ 如何重复插入一个相同的html结构呢? //错误的 window.onlo...
阅读 2955·2021-11-16 11:51
阅读 2585·2021-09-22 15:02
阅读 3701·2021-08-04 10:21
阅读 3552·2019-08-30 15:43
阅读 1922·2019-08-30 11:04
阅读 3583·2019-08-29 17:14
阅读 467·2019-08-29 12:16
阅读 2917·2019-08-28 18:31