重绘和回流
  aTeIOrZHygVI 2023年11月02日 54 0


浏览器的渲染过程

  1. 解析HTML,形成DOM树,当遇到非阻塞资源时,如图片则会继续解析,当遇到css文件时,也会继续解析。当遇到js文件的阻塞渲染,会停止html的解析。
  2. 构建CSSOM树。浏览器将css规则转换为可以理解和使用的样式映射。浏览器遍历CSS中的每个规则集,根据CSS选择器创建具有父、子和兄弟关系的节点树。
  3. 第三步是将DOM和CSSOM组合成一个Render树,计算样式或渲染树从DOM树的根开始构建,遍历每个可见节点。像和它的子节点以及任何具有​​display:none​​​ 样式的节点,例如​​script {display:none;}​​​ 这些标签将不会显示,也就是它们不会出现在Render树上。具有​​visibility:hidden​​ 的节点会出现在Render树上,因为它们会占用空间。由于我们没有给出任何指令来覆盖用户代理默认值,因此上面代码示例中的script节点将不会包含在Render树中。
  4. 第四步是在渲染树上运行布局以计算每个节点的几何体。(回流/重排)。在此基础上,考虑到视区大小,浏览器将确定屏幕上所有不同框的尺寸。以视区的大小为基础,布局通常从body开始,用每个元素的模型属性排列所有body的子孙元素的尺寸,为不知道其尺寸的替换元素(例如图像)提供占位符空间。
  5. 最后一步是将各个节点绘制到屏幕上。

回流:

以视区的大小为基础,布局通常从body 开始,用每个元素的框模型属性排列所有的body的子孙元素的尺寸,为不知道其尺寸的替换元素(例如图像)提供占位符空间。
总之,就是计算它们在设备视口(viewport)内的确切位置和大小(也就是几何属性和位置),这个计算的阶段就是回流。

重绘:

我们可以将渲染树上的每个节点都转换为屏幕上的实际像素,这个阶段就叫做重绘节点。也就是在屏幕上绘制图形,但是如果背景颜色发生改变,那么会引起重绘,但是不会发生回流。

回流一定会触发重绘,重绘不一定会触发回流。

触发回流重绘的操作

  1. 添加或删除可见的DOM元素
  2. 元素的位置发生变化
  3. 元素的尺寸发生变化(包括外边距、内边距、边框大小、高度和宽度等)
  4. 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。
  5. 页面一开始渲染的时候(这肯定避免不了)
  6. 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)

浏览器的优化机制

由于每次重排都会造成额外的计算消耗,因此大多数浏览器都会通过队列修改并批量执行来优化重排过程。浏览器会将修改操作放入到队列里,直到过了一段时间或者操作达到了一定阈值,才会清空队列。但是,当你获取布局信息的操作的时候,会强制队列刷新,比如当你访问以下属性或者使用以下方法:

  • offsetTop、offsetLeft、offsetWidth、offsetHeight
  • scroolTop、scroolLeft、scroolWidth、scroolHeight
  • clientTop、clientLeft、clientWidth.clientHeight
  • getComputedStyle()
  • getBoundingClientRect

因此我们在修改样式的时候,最好避免使用上面列出的属性,他们都会刷新渲染队列。如果要使用它们,最好将值缓存起来。

减少回流和重绘的方法:

  1. 把多个DOM操作合并在一起,使用csstext或者class
  • 使用cssText
const el = ducument.getElementById('test');
el.style.cssText += 'border-left: 1px;border-right: 2px; padding: 5px;';
  • 修改css的class
const el = document.getElementById('test')
el.className += 'active';
  1. 使得节点脱离文档流(也就是不可见的节点),操作,回到文档流。
  • 使用​​display:none​
  1. 必须触发布局事件
    也就是offset。如果多次用到同一个offset,那么可以先把它的值保存起来再使用。
  2. 对于比较复杂的动画可以使用绝对定位使其脱离文档流。对于复杂动画效果,由于经常会引起回流重绘,因此,我们可以使用绝对定位使其脱离文档流,否则会引起父元素以及后续元素频繁的回流。


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  p2QdBCa7ky7t   2023年11月02日   20   0   0 cssiframeSelenium
  1BVmdlLr07sm   2023年11月30日   63   0   0 HTMLcss
aTeIOrZHygVI
作者其他文章 更多

2023-11-02

2023-11-02

最新推荐 更多