浏览器中的回流重绘

314 阅读3分钟

前言

本篇文章讲一个面试的知识点,在浏览器上输入URL地址直到你看到页面的那一刻发生了什么?这个问题考察了特别多的知识点,可以说贯穿了前端的一生。接下来我们一起来看一下吧。

输入URL到页面渲染 (前半段)

简单描述一下当在浏览器上输入URL会向服务器发请求拿到数据,以百度首页为例,向百度的服务器发请求,中间其实有一些操作比如找IP,握手,发送有误重新发送等等,这里不做详细的描述,我们就可以在Network中看到拿到了百度首页的HtmlCss

2.png

后半段

浏览器获取到页面资源然后后做了什么呢?

  1. 浏览器加载HTML代码,将其解析成 DOM 树。
  2. 加载 CSS 代码, 将其解析成 CSSOM 树。
  3. DOM Tree + CSSOM Tree = render Tree

用代码表示一下:

 var DOMTree = {
    div: {
      id: 'app',
      style: 'width: 200px, height: 200px',
      children: {
        div: {
          clas: 'box',
          children: {
            p: {
              text: 'hello'
            }
          }
        }
      }
    }
  }


  var CSSOMTree = {
    '#app': {
      width: '200px',
      height: '200px'
    },
    '.box': {
      width: '100%',
      height: 100%;
      background: #000;
    }
     '#app .box p': {

     }
  }
  1. 计算布局,render树中的每一个节点都会计算一遍(这就叫做回流)。
  2. GPU 绘制 一个又一个的图层 (重绘)

回流

具体定义

当页面布局和几何属性发生改变时,浏览器需要重新计算元素的位置和大小,然后重新构建页面的布局树。这个过程是比较耗费性能的,因为它需要遍历整个布局树,计算每个元素的位置和大小,并且可能会触发其他元素的回流。

触发回流的操作

  1. 视窗大小变化。
  2. DOM几何属性发生变化。
  3. 添加或者删除DOM。
  4. offsetWidth, offsetHeight..., clientWidth, clientHeight..., scrollTop...。

局部回流

局部回流是指在DOM树中的某个特定区域内发生的回流。只有一部分DOM元素的布局发生变化,这时只需要进行局部回流。

重绘

具体定义

当元素的外观发生改变,但并不影响其布局属性(位置和大小)时,浏览器会重新绘制这个元素的外观。重绘不会引起布局树的重新构建,因此比回流的代价要小。

触发重绘的操作

  1. 修改元素的color
  2. 修改元素的background
  3. 修改元素的border-radius
  4. 修改元素的box-shadow
  5. 修改元素的背景图。

回流和重绘的发生是自动的,由浏览器引擎来处理的。回流一定重绘,重绘不一定回流。

优化性能

频繁的回流和重绘操作会导致页面性能下降,优化页面性能的关键之一就是尽量减少回流和重绘的发生次数。

  1. 当一个DOM节点display:none时,它便不参加render树的构建。
  2. 页面添加额结构,使用虚拟文档片段(DocumentFragment)进行多个 DOM 操作,然后一次性插入文档中。
  3. 避免频繁访问布局相关的属性,比如 offsetTopoffsetLeft,因为它们会触发回流。
  4. 使用克隆元素。

小结

减少回流和重绘对于各种类型的网页应用都非常重要,尤其是那些需要频繁操作DOM元素的复杂应用,如交互式网页、动画效果、数据可视化等。通过优化回流和重绘,可以改善网页的性能、用户体验和能源效率,提升网页应用的质量和可用性。