性能优化中,减少重绘重排应该是一种很好的优化方式,我们具体看一下什么情况下会造成重绘重排,为什么减少重绘重排可以做到优化,怎么样减少重绘重排。

浏览器渲染过程

我们先看看当浏览器拿到服务端返回的资源时,是如何渲染的。

首先浏览器会进行文件解析,主要解析三个东西:

  1. 解析 html/xhtml/svg,形成 dom 树。
  2. 解析 css,产生 CSS Rule Tree。
  3. 解析 js,js 会通过 api(包括 DOM API 和 CSSOM API) 来操作 Dom Tree 和 CSS Rule Tree。

解析完成之后

  1. 通过 CSS Rule Tree 和 Dom Tree 生成 rendering Tree。其中不包括 display:none 的元素。
  2. 计算 DOM 节点的位置,对元素进行分层及布局,也叫 reflow 和 layout 过程。

布局完成之后,就要进行绘制了,将各层发给 GPU,GPU 将各层合成,显示在屏幕上,即 composite。

什么情况下会造成重绘重排

当我们开始绘制的时候,如果使用 js 操作了 dom 元素,或者改变了 css 属性,就可能会造成重绘(repaint)和重排(reflow)。

repaint:屏幕的一部分进行了重画,比如某个 css 中改变背景色,元素尺寸没有变。 reflow:任何一个元素的尺寸发生了变化,需要重新验证并计算 render tree,就会造成重排。

在 PC 时代,我们用 jquery 进行获取元素,改变元素的尺寸,及时发生重排,我们也很难感知到,但是当移动时代到来之后,如果频繁发生重排,那手机就会受不了了。

尤其是在执行下面操作时,成本会很高:

  1. js 添加或者删除元素的时候
  2. js 改变元素的位置发生改变时
  3. 页面初始化
  4. 容器尺寸发生变化。比如在标准盒模型下添加 padding,border 就会造成重排,所以在书写样式的时候,很多会将盒模型设计成怪异盒模型(box-sizing: border-box)
  5. js 获取元素的尺寸单位。
  • offsetTop, offsetLeft, offsetWidth, offsetHeight
  • scrollTop/Left/Width/Height
  • clientTop/Left/Width/Height
  • IE 中的 getComputedStyle(), 或 currentStyle

如果发生上述的行为基本都会造成重绘和重排。

所以,当发生重排时,一定会发生重绘,但是发生重绘不一定会发生重排。

浏览器中每个元素节点都有 reflow 方法,当一个元素发生 reflow 时,他的子节点都会发生 reflow。

举几个例子来说明一下造成重绘重排的情况:

var bodyStyle = document.body.style; // cachebodyStyle.padding = '20px'; // reflow, repaintbodyStyle.border = '10px solid red'; // 再一次的 reflow 和 repaintbodyStyle.color = 'blue'; // repaintbodyStyle.backgroundColor = '#fad'; // repaintbodyStyle.fontSize = '2em'; // reflow, repaint// new DOM element - reflow, repaintdocument.body.appendChild(document.createTextNode('children!'));

为什么减少重绘重排可以优化性能

前面说了浏览器的渲染机制,多一次重绘就需要浏览器重新进行一次绘制,及时 GPU 处理会比较快,但是也是吃不消的,更别说重排了,重排一个 dom,会重新生成 render Tree,然后重新绘制。

如何减少重绘重排

其实浏览器很聪明,不可能每次修改样式就 reflow 或者 repaint 一次,一般来说,浏览器会积累一批操作,然后做一次 reflow。

但是也有些例外情况,比如 resize 窗口,改变窗口字体,浏览器会立即进行 reflow。

虽然浏览器会这么做,但是我们也应该减少重绘重排的次数,在开发阶段就为浏览器进行特殊的关爱,毕竟是每天陪伴我们的小伙伴。

下面总结了一些针对 reflow 和 repaint 的最佳实践:

  1. 不要把 DOM 元素的属性值放到一个循环中当成循环的变量。
  2. 尽可能的修改低层级的节点,避免修改高层级的节点,造成大面积的 reflow。
  3. 千万不要使用 table 布局,修改一小块地方,会造成整个 table 重新布局。
  4. 动画尽量使用 css 动画,css 动画中尽量只使用 transform 和 opacity,这不会发生重排和重绘
  5. 不要一条一条的修改 DOM 样式,尽量提前设置好 class,后续增加 class,进行批量修改。
  • 把 DOM 离线后修改。使用 documentFragment 对象在内存里操作 DOM。
  • 使用 requestAnimationFrame 可以进行优化,在下一帧进行操作。
  • 把修改频繁的元素先 display: none,修改完之后显示,修改个 100 次也无妨。
  • clone 一个 dom 节点在内存里,修改之后;与在线的节点相替换。

composite

当每次布局完成之后,就会发生 composite 过程,浏览器都把重绘后的图像发给 GPU 去合成并显示。

在上面最佳实践中最后提到了动画,动画其实是比较耗费性能的,因为动画的每一帧都会发给 GPU 去合成,重绘重排会发生在动画的每一帧。

我们在写动画的时候,可以通过 js 写,也可以通过 css 写。两种方式在写动画时,过程也是不一样的。

  1. js 写的动画,过程:js 计算 -> 重排(若布局改变) -> 重绘 -> 合成
  2. css 动画,过程:重排(若布局改变)-> 重绘 -> 合成

所以不难看出,耗费性能最少并能并最流畅的动画是只触发合成。

为了仅发生 composite,我们做动画的 css property 必须满足以下三个条件:

  1. 不影响文档流。
  2. 不依赖文档流。
  3. 不会造成重绘。

满足以上以上条件的 css property 只有 transform 和 opacity。

这样的话,由于没有重排和重绘,只有合成,那么浏览器在动画执行之前就知道动画如何开始和结束。

并且有两个优势:

  1. 动画将会非常流畅
  2. 动画不在绑定到 CPU,即使 js 执行大量的工作;动画依然流畅

事实上影响动画流畅性的因素不止重排重绘,还有 CPU 内存。

css 动画有一个重要的特性,它是完全工作在 GPU 上。因为你声明了一个动画如何开始和如何结束,浏览器会在动画开始前准备好所有需要的指令;并把它们发送给 GPU。

而如果使用 js 动画,浏览器必须计算每一帧的状态;为了保证平滑的动画,我们必须在浏览器主线程计算新状态;把它们发送给 GPU 至少 60 次每秒。

除了计算和发送数据比 css 动画要慢,主线程的负载也会影响动画; 当主线程的计算任务过多时,会造成动画的延迟、卡顿。

所以最佳实践中最后一条就提到了,在写动画时,尽量写 css 动画,并且尽量用 transform 和 opacity。

辅助工具

谷歌浏览器检测重绘工具:右上角三点->更多工具->开发者工具->Performance。

chrome浏览器的Performance是页面性能分析的利器,网上有很多关于关于如何去使用和查看Performance的文章,这里就不多做阐述了,大伙可以多去了解了解。

小结

总之,页面性能优化是前端从初级到高级都避不开的一个话题,如何做到性能的最优化更是一个资深前端应该考虑的事情,这里也希望有更好更多见解的小伙伴能够私聊我,给我点意见。

android 重绘如何能不闪一下屏幕_浏览器渲染机制——重绘重排相关推荐

  1. android 重绘如何能不闪一下屏幕_回流和重绘

    浏览器的渲染过程 本文先从浏览器的渲染过程来从头到尾的讲解一下回流重绘,如果大家想直接看如何减少回流和重绘,优化性能,可以跳到后面.(这个渲染过程来自MDN) 从上面这个图上,我们可以看到,浏览器渲染 ...

  2. android 重绘如何能不闪一下屏幕_前端性能优化之重绘和重排

    性能优化中,减少重绘重排应该是一种很好的优化方式,我们具体看一下什么情况下会造成重绘重排,为什么减少重绘重排可以做到优化,怎么样减少重绘重排. 浏览器渲染过程 我们先看看当浏览器拿到服务端返回的资源时 ...

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

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

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

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

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

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

  6. dev 中 gridcontrol1 滚动条重绘_浏览器的重绘和回流(Repaint amp; Reflow)

    参考文献: https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree ...

  7. 浏览器渲染页面的原理及流程---------重绘与重排(回流)--优化

    浏览器渲染页面的原理及流程 浏览器将域名通过网络通信从服务器拿到html文件后,如何渲染页面呢? 1.根据html文件构建DOM树和CSSOM树.构建DOM树期间,如果遇到JS,阻塞DOM树及CSSO ...

  8. 抽象手绘七夕情人节快闪PPT模板

    模板介绍 抽象手绘七夕情人节快闪PPT模板.一套节日PPT幻灯片模板,内含橙色,蓝色,紫色多种配色,风格设计,动态播放效果,精美实用. 希望下面这份精美的PPT模板能给你带来帮助,温馨提示:本资源使用 ...

  9. android 9 申请动态权限android.permission.WRITE_EXTERNAL_STORAGE 允许后应用闪退

    问题描述:如题,在调试android 9 高通msm8953平台时,客户反馈应用在允许Manifest.permission.WRITE_EXTERNAL_STORAGE权限后,应用闪退. 从log分 ...

最新文章

  1. 卸载linux系统装win,如何在计算机上删除 Linux 并安装 Windows
  2. table合并单元格colspan和rowspan
  3. DL之SqueezeNet:SqueezeNet算法的架构详解
  4. 【Python】Pygame入门
  5. 三步捋清链表相关题型!
  6. 【cocos2d-x】对CCSprite进行高斯模糊
  7. linux怎样判断线程是否暂停_怎样寻找合适的创业项目?如何判断一个创业项目是否靠谱?...
  8. CSDN文章标题名不能有%-6A这样的字串
  9. android.util.typedvalue的jar包,android – 了解Typed值类
  10. 2021-03-04
  11. linux文件复制和移动
  12. 基于python对B站缓存视频的批量复制,重命名
  13. 阿里云 mysql 100_【故障公告】阿里云 RDS 数据库服务器 CPU 100% 造成全站故障
  14. 怎么停止skywalking_SkyWalking 告警设置
  15. SpringBoot集成Dubbo
  16. 怎么检查新买的mac是不是原封正品
  17. 如何使用easywechat开发微信支付功能
  18. TCP是如何传输数据的?
  19. 我的一周re学习总结
  20. 米家电磁炉显示e10_米家电磁炉深度使用解析 这才是我想要的

热门文章

  1. java重新组合_Java 合并Word文档
  2. Maltego更新到4.2.6
  3. Xamarin SQLite教程Xamarin.iOS项目添加引用
  4. 邀请别人进入队伍rust_林俊杰组建DOTA2队伍,原Newbee五人被终身禁赛
  5. python pillow库_python pillow模块用法
  6. rust怎么把门拿下来_皮肤好的女生都是怎么护肤的?快拿小本本记下来
  7. UnicodeEncodeError: 'gbk' codec can't encode character '\U0001f349' in position 64: illegal multibyt
  8. python requests cookies请求_python的requests库怎么发送带cookies的请求
  9. EEGNet: 神经网络应用于脑电信号
  10. [pyinstaller] “RuntimeError: No metadata path found for distribution ‘greenlet‘