整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

6、怎么理解回流跟重绘?什么场景下会触发?

6、怎么理解回流跟重绘?什么场景下会触发?


  • 流:布局引擎会根据各种样式计算每个盒子在页面上的大小与位置
  • 重绘:当计算好盒模型的位置、大小及其他属性后,浏览器根据每个盒子特性进行绘制

聊一下

小时候最喜欢玩4399小游戏了,放学回家麻溜地打开电脑开始4399之旅。那么当我输入4399.com到页面加载完毕,这之间究竟发生了点什么事呢?

输入4399.com

浏览器加载到资源

我们输入4399.com,按下回车的那一瞬间,命运的齿轮开始转动

众所周知,我们的每一个页面都是由html、css组成的,所以你可以理解以下过程:

  1. 浏览器解析html代码,生成一个DOM树
  2. 浏览器解析css代码,生成一个CSSOM树
  3. 将DOM树和CSSOM树结合,去除不可见的元素,生成 Render Tree
  4. 计算布局(回流|重排),根据Render Tree 进行布局的计算,得到每一个节点的几何信息
  5. 绘制页面(重绘),GPU根据布局信息绘制

当页面重绘完毕后,我们就可以看到4399首页页面了

在上面的流程中,我们可以看到回流和重绘,那么什么是回流,什么又是重绘?

回流

  1. 什么是回流?
  • 浏览器计算页面布局的过程叫做回流

在上面提到,在生成Render Tree以后开始计算页面布局,此时发生的就是回流。我们的屏幕上有许多个物理发光点,在这里就是要计算要让哪个发光点亮起来,但是此时仅计算而已,要让屏幕亮起来,还得交给接下来的重绘

  1. 什么时候发生回流
  • 当一个容器的几何数学发生变更时,页面会发生回流
  • 1> 改变窗口的尺寸
  • 2> 改变元素的尺寸
  • 3> 增加或者删除可见元素
  • 4> 页面初次渲染
  • 5> ...

重绘

  1. 什么是重绘
  • 将已经计算好布局的容器在屏幕上展现出来

在回流中,我们已经计算好了要让哪些发光点亮起来,在重绘中进行的操作就是让发光点亮起来

  1. 什么时候发生重绘
  • 元素的非几何属性变化时,会发生重绘
  • 1> 修改背景颜色
  • 2> 修改背景图片
  • 3> 修改边框颜色
  • 4> 修改字体颜色

理解回流和重绘

回流主要是时刻注意屏幕上的几何图形的变化

例如,当屏幕上的矩形变成圆形的时候,屏幕上物理发光点的数量和位置肯定要发生变化,此时发生回流, 那么发生重绘吗?当然,物理发光点的变化肯定会发生重绘的,有些发光点要亮起来,有些要暗下去...

重绘主要是观察物理发光点的变化

此时,我们的物理发光点的位置没有改变,但是颜色改变,所以只触发了重绘,而并没有回流

总结:

回流一定重绘,重绘不一定回流

浏览器的优化策略

由于回流和重绘涉及对页面进行重新计算和绘制,因此它们可能会消耗大量的计算资源和时间。这可能导致页面加载速度变慢、页面响应性能下降,甚至导致卡顿和不流畅的用户体验。

优化策略的目的是减少不必要的回流和重绘,从而提高页面的性能和用户体验。

当代浏览器都有一个渲染队列机制,当我们改变一个元素的样式 从而导致浏览器需要回流时,这个操作会进入渲染队列,然后浏 览器继续往下执行代码,如果还有相同行为,继续进入队列,直到 下面没有样式修改,浏览器会批量化渲染队列中的回流过程,这只 发生一次回流

简而言之,就是一下把所有的回流全都存起来,直到队列满了,或者碰到一些要强制执行队列的东西才开始执行队列中的回流

哪些属性会导致渲染队列强制执行呢?

读取容器几何信息:

offsetTop,offsetLeft,offsetWidth,offsetHeight

clientWidth,clienLeft,clientHeight,clientTop

ScrollHeight,ScrollTop,ScrollWidth,ScrollLedt

以上这些属性全部都会导致浏览器的渲染队列强制执行(当渲染队列中没东西时,不触发回流)

字节面试题

以下这段代码,发生几次回流?

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script>
let el=document.getElementById('app')
el.style.width=(el.offsetWidth + 1) + 'px'
el.style.width=1 + 'px'
</script>
</body>
</html>

答案是一次回流

当运行到el.style.width=(el.offsetWidth + 1) + 'px'时,由于遇到el-offsetWidth,读取了容器的几何信息,所以强制执行渲染队列,但是此时渲染队列中啥也没有...于是不执行。

然后让el.style.width=(el.offsetWidth + 1) + 'px',此时这段回流往渲染队列里存入,继续向下走

el.style.width=1 + 'px'样式改变,此次回流往渲染队列中加入,再向下走,发现没有回流了,于是开始执行渲染队列,一次执行完毕,发生一次回流...

结尾

分享完毕~~


作者:滚去睡觉
链接:https://juejin.cn/post/7322723692743573514

面的绘制时间(paint time)是每一个前端开发都需要关注的的重要指标,它决定了你的页面流畅程度。而如何去观察页面的绘制时间,找到性能瓶颈,可以借助Chrome的开发者工具。



回流与重绘

1. 当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程成为重绘。

2. 当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。

注意:回流必将引起重绘,而重绘不一定会引起回流。

回流何时发生:

当页面布局和几何属性改变时就需要回流。下述情况会发生浏览器回流:

  1. 页面渲染初始化;
  2. 调整窗口大小(Resizing the window),浏览器窗口尺寸改变——resize事件发生时
  3. 增加或者移除样式表(Adding or removing a stylesheet)
  4. 元素位置改变、元素尺寸改变——width/height/padding/border/margin
  5. 内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;
  6. 改变字体(Changing the font)
  7. 激活 CSS 伪类,比如 :hover (IE 中为兄弟结点伪类的激活)(Activation of CSS pseudo classes such as :hover (in IE the activation of the pseudo class of a sibling))
  8. 操作 class 属性(Manipulating the class attribute)
  9. 脚本操作 DOM(A script manipulating the DOM),添加或者删除可见的DOM元素;
  10. 计算 offsetWidth 和 offsetHeight 属性(Calculating offsetWidth and offsetHeight)
  11. 设置 style 属性的值 (Setting a property of the style attribute)

这么多,分类整理记忆下:

js请求以下style信息时,触发回流(浏览器会立刻清空队列:)

  • clientWidth、clientHeight、clientTop、clientLeft
  • offsetWidth、offsetHeight、offsetTop、offsetLeft
  • scrollWidth、scrollHeight、scrollTop、scrollLeft
  • width、height
  • getComputedStyle()
  • getBoundingClientRect()

css中如下属性,触发回流

  • width/height/padding/border/margin
  • font/line-height/font-weight/
  • postion/display/float/clear/

js操作DOM,修改class属性,修改样式表,修改文档内容,修改元素计算样式

让我们看看下面的代码是如何影响回流和重绘的:

ar s=document.body.style;
s.padding="2px"; // 回流+重绘
s.border="1px solid red"; // 再一次 回流+重绘
s.color="blue"; // 再一次重绘
s.backgroundColor="#ccc"; // 再一次 重绘
s.fontSize="14px"; // 再一次 回流+重绘
// 添加node,再一次 回流+重绘
document.body.appendChild(document.createTextNode('abc!'));

然而这些都是意淫:那么

怎么监控重绘回流

chorme 按下:f12,然后按下 esc……

但是,我按了没有 readering

那是你没有勾选啊,console 旁边有三点是不是,点击,然后勾选,rendering……

以上5个选项的意思如下:

  1. Show paint rectangles 显示绘制矩形
  2. Show composited layer borders 显示层的组合边界(注:蓝色的栅格表示的是分块)
  3. Show FPS meter 显示FPS帧频
  4. Enable continuous page repainting 开启持续绘制模式 并 检测页面绘制时间
  5. Show potential scroll bottlenecks 显示潜在的滚动瓶颈。


优化重绘回流

CSS


  • 避免使用table布局。
  • 尽可能在DOM树的最末端改变class。
  • 避免设置多层内联样式。
  • 将动画效果应用到position属性为absolute或fixed的元素上。
  • 避免使用CSS表达式(例如:calc())。


JavaScript


  • 避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
  • 避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
  • 也可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。
  • 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
  • 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。基本原则就是,把动画元素用position:absolute踢出文档流,这样R&R就限制在了absolute元素的子节点。告诉浏览器,我这块结构跟其他的单独渲染,不要搅和全页面了。


参看文章:

回流与重绘:CSS性能让JavaScript变慢?






转载本站文章《chrome对页面重绘和回流以及优化进行优化》,
请注明出处:https://www.zhoulujun.cn/html/webfront/browser/webkit/2016_0506_7820.html