浏览器的重排与重绘是什么意思?
准备
为了理解重排与重绘,我们首先需要了解一点浏览器渲染的基础知识 ~
网页生成分为五步:
1. HTML 被 HTML 解析器解析成 DOM 树
2. CSS 被 CSS 解析器解析成 CSSOM 树
3. 结合 DOM 树和 CSSOM 树,生成一颗渲染树(Render Tree)
4. 将所有渲染树的所有子节点进行平面合成,生成布局(flow) -- 重排(也叫回流)
5. 将布局绘制(paint)在屏幕上 -- 重绘
其中 4 5 步是最耗时的,这两步就是我们常说的 渲染
网页生成时候,至少会渲染一次,在用户访问的过程中,可能会不断的重新渲染,即执行上述第 4 5 步,或者只执行第 5 步。
简单来说:
重排指重新生成布局,重新排列元素。例如margin: 10px 变成 margin: 20px,会导致重排;
重绘指重新描绘已经生成的布局。例如颜色改变,不会改变布局,只是重新描绘颜色而已;
重排必定会导致重绘,重绘不一定有重排。因为重排在重绘前执行。所以上述 margin 改变 ,重排完成后触发重绘,成本是很高的。
为什么 width height margin 会引起重排+重绘,color transform 仅会导致重绘呢?
CSS的最终表现分为以下四步:
Recalculate Style -> Layout -> Paint Setup and Paint -> Composite Layers
查找并计算样式 -> 排布 -> 绘制 -> 组合层
width height margin 位于 Layout 层,color transform 位于 Composite Layers
遵循从前到后顺序影响的原则:Layout 改变必定触发 Paint Setup and Paint 和 Composite Layers ,color transform 仅会触发 Composite Layers
所以 ~ 我们得到了答案
1 重排
1.1 影响范围
全局范围:从根节点 html 开始对整个 Render Tree 进行重新布局
局部范围 :对 Render Tree 的某小部分进行重新布局
/* 更改下例 <p> 的 width height,会对h2,h3,body,html都产生影响*/
<html><body><div><h2>hello</h4><p>word</p><h3>!</h5></div></body>
</html>/* 更改下例 <p> 的 width height,若不超出div的范围,则只在div这个dom内触发重排,产生局部影响*/
<html><body><div style="width:100px;height:100px"><h2>hello</h4><p>word</p><h3>!</h5></div></body>
</html>
1.2 引起重排的属性和方法
width | height | margin | padding |
display | border | position | overflow |
clientWidth | clientHeight | clientTop | clientLeft |
offsetWudth | offsetHeight | offsetTop | offsetLeft |
scrollWidth | scrollHeight | scrollTop | scrollLeft |
scrollIntoView() | scrollTo() | getComputedStyle() | |
getBoundingClientRect() | scrollIntoViewIfNeeded() |
2 重绘
2.1 引起重绘的属性
color | border-style | visibility | background |
text-decoration | background-image | background-position | background-repeat |
outline-color | outline | outline-style | border-radius |
outline-width | box-shadow | background-size |
3 性能优化
原则:减少重排次数,重排范围
参考:https://segmentfault.com/a/1190000017491520
根据浏览器的渲染队列机制,我们在js文件中尽量少用以下样式请求:(下列会强制刷新队列,让浏览器立即执行重排加重绘)
- offsetTop, offsetLeft, offsetWidth, offsetHeight
- scrollTop, scrollLeft, scrollWidth, scrollHeight
- clientTop, clientLeft, clientWidth, clientHeight
- getComputedStyle(), currentStyle()
浏览器渲染机制:
浏览器把引起重排重绘的操作放入队列中,等到队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器再批量执行这些操作;
// 例如:以下仅会触发1次重排+重绘 div.style.left = '10px'; div.style.top = '10px';
但是有些操作,就会使浏览器立即执行渲染任务,比如以下例子:
// 例如:下列会触发2次重排+重绘 // 因为队列中,可能会有影响到这些值的操作,为了给我们最精确的值,浏览器会立即重排+重绘 div.style.left = '10px'; console.log(div.offsetLeft); div.style.top = '10px'; console.log(div.offsetTop);
优化举例:
3.1 样式集中改变
// bad
var left = 10;
var top = 10;
el.style.left = left + "px";
el.style.top = top + "px";
// good
el.className += " theclassname";
// good
el.style.cssText += "; left: " + left + "px; top: " + top + "px;";
建议通过改变 class 或者 csstext 属性集中改变样式
3.2 分离读写操作
div.style.left = '10px';
div.style.top = '10px';
console.log(div.offsetLeft);
console.log(div.offsetTop);
上面触发2次重排+重绘的代码,这次只触发了一次重排
3.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';
3.4 离线改变 dom
隐藏要操作的 dom
在要操作 dom 之前,通过 display 隐藏 dom,当操作完成之后,才将元素的 display 属性为可见,因为不可见的元素不会触发重排和重绘
// 修改 dom 样式前
dom.display = 'none'
// 修改 dom 样式后
dom.display = 'block'
- 通过使用 DocumentFragment 创建一个
dom
碎片,在它上面批量操作 dom,操作完成之后,再添加到文档中,这样只会触发一次重排 - 复制节点,在副本上工作,然后替换它
3.5 position 属性为 absolute 或 fixed
position 属性为 absolute 或 fixed 的元素(脱离文档流),重排开销比较小,不用考虑它对其他元素的影响
3.6 优化动画
- 可以把动画效果应用到 position 属性为 absolute 或 fixed 的元素上,减少对其他元素的影响
- 动画效果还应牺牲一些平滑,来换取速度,这中间的度自己衡量:比如实现一个动画,以1个像素为单位移动这样最平滑,但是 reflow 就会过于频繁,大量消耗 CPU 资源,如果以3个像素为单位移动则会好很多。
- 启用 GPU加速
此部分来自 优化CSS重排重绘与浏览器性能
GPU(图像加速器):
GPU 硬件加速是指应用 GPU 的图形性能对浏览器中的一些图形操作交给 GPU 来完成,因为 GPU 是专门为处理图形而设计,所以它在速度和能耗上更有效率。
GPU 加速通常包括以下几个部分:Canvas2D,布局合成,CSS3 转换(transitions),CSS3 3D 变换(transforms),WebGL 和视频 (video)。
/** 根据上面的结论* 将 2d transform 换成 3d* 就可以强制开启 GPU 加速* 提高动画性能*/
div {transform: translate3d(10px, 10px, 0);
}
4 diff算法
首先奉上本人结合Vue v-for 讲解diff算法的博客~
大家都知道 React 中状态变化后,UI层会及时响应,但是状态变化后并不会立即去计算并渲染DOM数的变化部分,是先建立一个虚拟DOM,改动首先同步到虚拟DOM中,最后在批量同步到真实DOM中。不是每次改动都操作真实DOM。
为什么不能每次改变都直接去操作DOM树?
这便是因为在浏览器中,每一次DOM操作都有可能引起重绘或重排(回流),这太昂贵了,如果每一次改变都直接对DOM进行操作,这会带来性能问题,而批量操作只会触发一次DOM更新。
《Flutter实战》这本书上作者提出了一个思考题,我认为不错,在此分享,欢迎大家留言交流!
思考题:Diff 操作和 DOM 批量更新难道不应该是浏览器的职责吗?第三方框架中去做合不合适?
未完待续 ~
浏览器的重排与重绘是什么意思?相关推荐
- java都界面相对布局_浏览器的重排和重绘
浏览器的高层结构 1.用户界面 - 包括地址栏.前进/后退按钮.书签菜单等. 2.浏览器引擎 - 在用户界面和呈现引擎之间传送指令. 3.渲染引擎 - 负责显示请求的内容. 4.网络 - 用于网络调用 ...
- 重排(reflow) 重绘(repaint)
在页面的生命周期中:至少会发生一次渲染,在用户访问的过程中,还会不断的触发重排(reflow)重绘(repaint) 重绘和重排都会影响性能,尤其是重排,会使我们付出高昂的性能代价. 页面生成的过程( ...
- 160826、浏览器渲染页面过程描述,DOM编程技巧以及重排和重绘
一.浏览器渲染页过程描述 1.浏览器解析html源码,然后创建一个DOM树. 在DOM树中,每一个HTML标签都有一个对应的节点(元素节点),并且每一个文本也都有一个对应的节点(文本节点). DO ...
- 浏览器渲染机制、重排、重绘
前言 浏览器的渲染机制.重排.重绘 一.页面生成 1. HTML会被HTMl解析器解析成DOM树 2. CSS会被CSS解析器解析成CSSOM树 3. 结合DOM树和CSSOM树生成一颗渲染树 4.将 ...
- 前端性能优化之重排和重绘
前言,最近利用碎片时间拜读了一下尼古拉斯的另一巨作<高性能JavaScript>,今天写的文章从"老生常谈"的页面重绘和重排入手,去探究这两个概念在页面性能提升上的作用 ...
- 你真的了解重排和重绘吗?
做过前端开发的小伙伴就算不是非常理解重排与重绘,但是肯定都听过这两个词.那为什么这两个东西这么重要?因为他与我们的页面性能息息相关,今天,我们就来好好研究一下这两个东西. 浏览器的渲染流程 在讲解重排 ...
- 简单易懂之什么是重排和重绘?
文章目录 目录 一.浏览器页面是怎么生成的? 二.什么是重排和重绘? 1.什么时候发生重绘? 2.如何优化重排效率? 一.浏览器页面是怎么生成的? 首先让我们来先了解一下浏览器页面生成的过程 文字解析 ...
- 什么是重排和重绘?何时会触发?
重排 当dom的变化影响了元素的几何信息(位置),浏览器需要计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排,表现为重新生成布局,重新排列元素. 重绘 当一个元素(颜色.字体颜色)的外 ...
- 【CSS笔记】CSS修饰表格、表单、CSS重排和重绘
目录 一.CSS修饰表格 1.1.CSS表格属性 (1)边框 (2)宽度和高度 (3)对齐方式 二.CSS修饰表单 2.1.CSS表单 三.CSS重排和重绘 3.1.HTML渲染过程 3.2.重排和重 ...
最新文章
- rtems线程管理与调度(一)
- Nginx —— 检查配置文件nginx.conf的正确性命令(-t)
- Algs4-1.5.4给出id[]和sz[]的内容与次数
- 预计2021年移动渠道将占中国网络广告支出82%
- ICLR 2020 | 多模态下使用图片信息显著增强机器翻译效果
- asp.net模态窗口返回值
- linux(3):Linux MBR分区、挂载操作步骤,逻辑卷扩容操作
- JavaScript学习(三十七)—实现右键自定义菜单的功能
- 编写javascript、Jquery的String.format();
- ios input框输入白屏
- 太阳能热水器工作原理
- oracle数据库与实例的区别与联系
- php做网站半成品,两小时学会用php做网站购物车
- 系列 | 数仓实践第三篇NO.3『拉链表』
- 音视频开发之旅(40)-贝塞尔曲线和曲面
- indexedDB数据库使用总结
- 转载-正斜杠‘/‘和反斜杠‘\‘的辨析✔
- Matlab实现普朗克函数
- java(若依)防止表单重复提交
- 甘肃陇南破“行路难” 连接珠三角融入长江经济带