准备


为了理解重排与重绘,我们首先需要了解一点浏览器渲染的基础知识 ~

网页生成分为五步:

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文件中尽量少用以下样式请求:(下列会强制刷新队列,让浏览器立即执行重排加重绘)

  1. offsetTop, offsetLeft, offsetWidth, offsetHeight
  2. scrollTop, scrollLeft, scrollWidth, scrollHeight
  3. clientTop, clientLeft, clientWidth, clientHeight
  4. 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 批量更新难道不应该是浏览器的职责吗?第三方框架中去做合不合适?

未完待续 ~

浏览器的重排与重绘是什么意思?相关推荐

  1. java都界面相对布局_浏览器的重排和重绘

    浏览器的高层结构 1.用户界面 - 包括地址栏.前进/后退按钮.书签菜单等. 2.浏览器引擎 - 在用户界面和呈现引擎之间传送指令. 3.渲染引擎 - 负责显示请求的内容. 4.网络 - 用于网络调用 ...

  2. 重排(reflow) 重绘(repaint)

    在页面的生命周期中:至少会发生一次渲染,在用户访问的过程中,还会不断的触发重排(reflow)重绘(repaint) 重绘和重排都会影响性能,尤其是重排,会使我们付出高昂的性能代价. 页面生成的过程( ...

  3. 160826、浏览器渲染页面过程描述,DOM编程技巧以及重排和重绘

    一.浏览器渲染页过程描述   1.浏览器解析html源码,然后创建一个DOM树. 在DOM树中,每一个HTML标签都有一个对应的节点(元素节点),并且每一个文本也都有一个对应的节点(文本节点). DO ...

  4. 浏览器渲染机制、重排、重绘

    前言 浏览器的渲染机制.重排.重绘 一.页面生成 1. HTML会被HTMl解析器解析成DOM树 2. CSS会被CSS解析器解析成CSSOM树 3. 结合DOM树和CSSOM树生成一颗渲染树 4.将 ...

  5. 前端性能优化之重排和重绘

    前言,最近利用碎片时间拜读了一下尼古拉斯的另一巨作<高性能JavaScript>,今天写的文章从"老生常谈"的页面重绘和重排入手,去探究这两个概念在页面性能提升上的作用 ...

  6. 你真的了解重排和重绘吗?

    做过前端开发的小伙伴就算不是非常理解重排与重绘,但是肯定都听过这两个词.那为什么这两个东西这么重要?因为他与我们的页面性能息息相关,今天,我们就来好好研究一下这两个东西. 浏览器的渲染流程 在讲解重排 ...

  7. 简单易懂之什么是重排和重绘?

    文章目录 目录 一.浏览器页面是怎么生成的? 二.什么是重排和重绘? 1.什么时候发生重绘? 2.如何优化重排效率? 一.浏览器页面是怎么生成的? 首先让我们来先了解一下浏览器页面生成的过程 文字解析 ...

  8. 什么是重排和重绘?何时会触发?

    重排 当dom的变化影响了元素的几何信息(位置),浏览器需要计算元素的几何属性,将其安放在界面中的正确位置,这个过程叫做重排,表现为重新生成布局,重新排列元素. 重绘 当一个元素(颜色.字体颜色)的外 ...

  9. 【CSS笔记】CSS修饰表格、表单、CSS重排和重绘

    目录 一.CSS修饰表格 1.1.CSS表格属性 (1)边框 (2)宽度和高度 (3)对齐方式 二.CSS修饰表单 2.1.CSS表单 三.CSS重排和重绘 3.1.HTML渲染过程 3.2.重排和重 ...

最新文章

  1. rtems线程管理与调度(一)
  2. Nginx —— 检查配置文件nginx.conf的正确性命令(-t)
  3. Algs4-1.5.4给出id[]和sz[]的内容与次数
  4. 预计2021年移动渠道将占中国网络广告支出82%
  5. ICLR 2020 | 多模态下使用图片信息显著增强机器翻译效果
  6. asp.net模态窗口返回值
  7. linux(3):Linux MBR分区、挂载操作步骤,逻辑卷扩容操作
  8. JavaScript学习(三十七)—实现右键自定义菜单的功能
  9. 编写javascript、Jquery的String.format();
  10. ios input框输入白屏
  11. 太阳能热水器工作原理
  12. oracle数据库与实例的区别与联系
  13. php做网站半成品,两小时学会用php做网站购物车
  14. 系列 | 数仓实践第三篇NO.3『拉链表』
  15. 音视频开发之旅(40)-贝塞尔曲线和曲面
  16. indexedDB数据库使用总结
  17. 转载-正斜杠‘/‘和反斜杠‘\‘的辨析✔
  18. Matlab实现普朗克函数
  19. java(若依)防止表单重复提交
  20. 甘肃陇南破“行路难” 连接珠三角融入长江经济带

热门文章

  1. GAE开发问题总结、GAE开发心得(我爱记账网-在线记账、网络记账、网上记账、家庭记账)
  2. 记账本微信小程序开发一
  3. OpenHarmony 平头哥玄铁架构 轻量系统移植—润和W800移植分享
  4. 企业后备人才管理体系的建立
  5. wordpress phpass java版本
  6. openmv ide 2.6.5下载
  7. 采购申请审批策略增强
  8. 个性化智能推荐系统分析与调研
  9. JTAG基本原理及仿真器性能比较
  10. 职业技能培训机构怎么用自媒体招生