重排和重绘的区别

如何理解重排和重绘?

回答:重排就是当页面的结构发生变化了,就会重排,比如改变变字体的大小,增删 DOM 元素这样的。重绘就是页面结构没有变化,只是外观变了,比如改了一下字体颜色、背景颜色这样的。就只会发生重绘。

上面的回答显然是不够的,下面我们来讲一下这个问题。我们知道,写了 HTML、CSS、JavaScript 就可以将页面渲染到屏幕上,但是浏览器是如何把我们的代码渲染到屏幕上的像素点的呢?这就需要了解到这么一个概念 CRP:关键渲染路径(Critical Rendering Path)是浏览器将 HTML,CSS 和 JavaScript 转换为屏幕上的像素所经历的步骤序列。优化关键渲染路径可提高渲染性能

大致步骤是这样:在解析 HTML 时会创建 DOM,HTML 可以请求 JavaScript,而 JavaScript 反过来,又可以更改 DOM。HTML 包含或请求样式,依次来构建 CSSOM。浏览器引擎将两者结合起来以创建 Render Tree (渲染树),Layout(布局)确定页面上所有内容的大小和位置,确定布局后,将像素 Paint (绘制)到屏幕上。

接下来研究一下详细的过程:

  • 生成 DOM
    DOM 构建是增量的。浏览器从远程下载 Byte => 根据相应的编码 (如 utf8) 转化为字符串 => 通过 AST 解析为 Token => 生成 Node => 生成 DOM。单个 DOM 节点以 startTag token 开始,以 endTag token 结束。节点包含有关 HTML 元素的所有相关信息。该信息是使用 token 描述的。节点根据 token 层次结构连接到 DOM 树中。如果另一组 startTag 和 endTag token 位于一组 startTag 和 endTag 之间,则在节点内有一个节点,这就是我们定义 DOM 树层次结构的方式。

  • 生成 CSSOM
    浏览器解析 css 文件,生成 CSSOM。CSSOM 包含了页面所有的样式,也就是如何展示 DOM 的信息。CSSOM 跟 DOM 很像,但是不同。DOM 构造是增量的,CSSOM 却不是。CSS 是渲染阻塞的:浏览器会阻塞页面渲染直到它接收和执行了所有的 CSS。CSS 是渲染阻塞是因为规则可以被覆盖,所以内容不能被渲染直到 CSSOM 的完成

  • Render Tree(渲染树)
    渲染树(Render Tree)包括了内容和样式:DOM 和 CSSOM 树结合为渲染树。为了构造渲染树,浏览器检查每个节点,从 DOM 树的根节点开始,并且决定哪些 CSS 规则被添加。渲染树只包含了可见内容(body 里的部分)。

  • Layout(布局)
    一旦渲染树被构建,布局变成了可能。布局取决于屏幕的尺寸。布局这个步骤决定了在哪里和如何在页面上放置元素,决定了每个元素的宽和高,以及他们之间的相关性。

  • Paint(绘制)
    最后一步是将像素绘制在屏幕上,栅格化所有元素,将元素转换为实际像素。一旦渲染树创建并且布局完成,像素就可以被绘制在屏幕上。加载时,整个屏幕被绘制出来。之后,只有受影响的屏幕区域会被重绘,浏览器被优化为只重绘需要绘制的最小区域。绘制时间取决于何种类型的更新被附加在渲染树上。绘制是一个非常快的过程,所以聚焦在提升性能时这大概不是最有效的部分。

了解完上面的关键路径渲染之后,再来了解重排和重绘简直就是小 case。

  • 重排(Reflow):元素的 位置发生变动 时发生重排,也叫回流。此时在 Layout 阶段,计算每一个元素在设备视口内的确切位置和大小。当一个元素位置发生变化时,其父元素及其后边的元素位置都可能发生变化,代价极高。
  • 重绘(Repaint): 元素的 样式发生变动 ,但是位置没有改变。此时在关键渲染路径中的 Paint 阶段,将渲染树中的每个节点转换成屏幕上的实际像素,这一步通常称为绘制或栅格化。

JavaScript 的执行是在生成渲染树之前的。这也是为什么 JavaScript 的加载、解析与执行会阻塞 DOM 的构建,阻塞页面的渲染。这其实是非常合理的:因为 JavaScript 可以修改网页的内容,它可以更改 DOM,如果不阻塞,那么这边在构建 DOM,那边 JavaScript 在改 DOM,如何保障最终得到的 DOM 是否正确?而且在 JS 中前一秒获取到的 DOM 和后一秒获取到的 DOM 不一样是什么鬼?它会产生一系列问题,所以 JS 是阻塞的,它会阻塞 DOM 的构建流程,所以在 JS 中无法获取 JS 后面的元素,因为 DOM 还没构建到那。就是为什么我们需要把 js 放在页面底部的原因,尽量保证 DOM 树生成完毕再去加载 JS,从而出现这样的效果。

性能优化

  • 减少 DOM 树渲染时间(譬如降低 HTML 层级、标签尽量语义化等等)。
  • 减少 CSSOM 树渲染时间(降低选择器层级等等)。
  • 减少 HTTP 请求次数及请求大小。
  • 将 css 放在页面开始位置。
  • 将 js 放在页面底部位置,并尽可能用 defer 或者 async 避免阻塞的 js 加载,确保 DOM 树生成完才会去加载 js。
  • 用 link 替代@import。
  • 如果页面 css 较少,尽量使用内嵌式。
  • 为了减少白屏时间,页面加载时先快速生成一个 DOM 树。

正确的回答:重排和重绘是浏览器关键渲染路径上的两个节点, 浏览器的关键渲染路径就是 DOM 和 CSSOM 生成渲染树,然后根据渲染树通过一个布局(也叫 layout)步骤来确定页面上所有内容的大小和位置,确定布局后,将像素 绘制 (也叫 Paint)到屏幕上。
其中重排就是当元素的位置发生变动的时候,浏览器重新执行布局这个步骤,来重新确定页面上内容的大小和位置,确定完之后就会进行重新绘制到屏幕上,所以重排一定会导致重绘。
如果元素位置没有发生变动,仅仅只是样式发生变动,这个时候浏览器重新渲染的时候会跳过布局步骤,直接进入绘制步骤,这就是重绘,所以重绘不一定会导致重排。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值