为什么回流会产生重绘,重绘不一定产生回流,浏览器输入地址到页面呈现发生了什么

本文详细介绍了从浏览器输入地址到页面呈现的整个过程,包括DNS域名解析、HTTP请求的TCP三次握手、渲染流程中的HTML解析、样式计算、布局、分层、绘制等步骤,以及重绘和回流的概念。在渲染过程中,浏览器会进行一系列复杂的操作,如构建DOM树、CSSOM树,然后进行布局计算和绘制,最后通过GPU进行光栅化和画。文章还探讨了回流(涉及布局和绘制)与重绘(仅涉及绘制)的区别和关系。
摘要由CSDN通过智能技术生成

浏览器输入地址到页面呈现发生了什么,为什么回流会产生重绘,重绘不一定产生回流



前言

简单的说: DNS域名解析(包含查询缓存) —> 建立http请求获取资源(包含查询缓存) —> 渲染绘制页面


一、查询缓存

如果之前访问过,浏览器会协商缓存
缓存,如响应头的缓存控制头(如Cache-Control、Expires等),浏览器先检查一遍缓存是否可用

  • 强缓存:比如设置了Expires 过期时间,在该时间内,就直接返回资源了
  • 协商缓存:请求资源的时候会带上请求头标识,额…了解个过程,不深究~,服务器去检验是否有效,通过了就返回304状态码,要是无效就正常返回200,并再响应头上带上缓存信息然后进入下一个缓存动作

1.1DNS域名解析

打开一个网站背后都是通过ip地址找到对应的服务器,但ip地址不容易记忆,所以出现了域名,如baidu.com, 一看就知道是百度,所以要想通信,必须先解析域名,这就是DNS干的事。

  1. 浏览器会在自己缓存里面查一遍,如果有对应的记录,就直接返回
  2. 浏览器找不到回去本地hosts文件里面查一遍,这里保存了域名和ip地址的映射关系
  3. 如果没找到回去本地DNS缓存服务器找一遍,还是没找到去其他DNS服务器查找
  4. 去访问下根域名服务器(迭代查询):告诉你一个线索,可能在哪哪哪能找到,你去找吧

1.2DNS服务器

DNS服务器是有层级关系的,大概分为:
本地域名服务器:没啥好说的
根域名服务器:全球只有13台,每个根域名服务器保存了所有顶级域名服务器的域名和ip地址
顶级域名服务器:这些域名服务器负责管理在该顶级域名服务器注册的所有二级域名
权限域名服务器: 负责一个区域里面的域名解析,每个主机的域名都会在这里注册,所以基本在这都能被查询到,呃~域名输的不对的不算

查询模式:

  • 迭代查询:大致就是访问根域名服务器,然后根服务器不会告诉你结果是啥,而是告诉你一个线索,让你去哪台顶级域名服务器里面去找找。A --> B —>A—>C----A
  • 递归查询:当对一个A域名服务器发起请求后,如果有就返回结果,如果没有此时会向B服务器查询请求,查到了,就返回给A,然后A再把结果返给你

二、http请求

域名解析获得ip后就可以和服务器打交道了

2.1 tcp三次握手

为什么要握手
是为了双方互相知道能不能发消息和能不能收消息的过程,只有双方都能发消息,都能收消息,带能通信,比如:

  1. A不能发消息,呃…也算一种情况吧,没法通信
  2. A发消息给B,B没法收,通信就断了
  3. A发消息给B,B收到了(此时B是知道A能发消息,但不清楚能不能收到消息,对于A,并不清楚B能不能收和发),如果B没法发消息,A永远也收不到消息,通信也断了
  4. A发消息给B,B收到了,然后对A发出了响应信息(此时B是知道A能发消息,但不清楚能不能收到消息,对于A,并不清楚B能不能收和发),
  5. A发消息给B,B收到了,然后对A发出了响应信息, 此时A如果没有收到(和4情况一致)
  6. A发消息给B,B收到了,然后对A发出了响应信息,A收到了(此时A知道B既能发消息也能收消息,A到B是通的,B只知道A能发,但不知道能不能收),需要A发送对B的响应消息,B才能知道A能收和能发,既然双方都能收,都能发就可容易正常通信了

为什么是三次,哪三次

打个比方:

  1. 第一次:土豆土豆,我是番茄,收到请回答,over~(A能发)
  2. 第二次:土豆收到,番茄请说,over(A能发,B能收也能发)
  3. 第三次:番茄吧啦吧啦吧啦~ (A能发能收,B能收能发)

这里网络线程开始下载资源

2.2网络线程

浏览器网络线程收到 HTML 文档后,会产生一个渲染任务,并将其传递给渲染主线程的消息队列,在事件循环的作用下,渲染主线程取出消息队列中的渲染任务,开启渲染流程

三、渲染

渲染流程分的八个阶段:解析HTML、样式计算、布局、分层、绘制、分块、光栅化、画。

3.1 解析HTML

网络线程下载收到的HTML实际为一个字符串,渲染主线程,对页面从上往下解析, 遇到外部css链接(link标签)为了提高解析效率,会启动预解析器线程,网络线程开始下载css,下载完成后预解析器线程解析css,构建cssom树,主线程html解析不会被中断css 不会阻塞html解析的根本原因),css解析完成后会合并到html; 如果遇到script,会停止解析HTML, 等待js下载完成,会立即解释执行,因为js代码的运行可能会修改当前dom树(这就是js会阻塞HTML解析的根本原因)。

注:这一步生成的cssom树并不是最终样式,可以在控制台打印一下 document.styleSheets。

解析完css后类型为StyleSheetList ,里面包含了多个CSSStyleSheet的样式表,每个CSSStyleSheet都包含了cssRules
在这里插入图片描述

3.2 样式计算

注:css属性值的计算过程 包含(层叠、权重、优先级,css继承等),计算后的树形会把预设值变成绝对值,相对单位变为绝对单位,比如color: red 会被转化为color: rgb(255, 0, 0); font-size: 2em会被转化为font-size: 24px(相对单位转换,24是举例子)

第一步生成的cssom树并不是最终样式,而是会形成一个样式表,第二渲染主线程会遍历得到的DOM树,一次会为树中的每个节点计算出他最终的样式,称为 Computed Style,合并后会产生一颗带样式的DOM树

注:此时还无法知道盒子的几何信息,如:节点的宽高,相对位置等,因为页面上的元素之间的位置和尺寸是相互影响的,一个元素的位置和尺寸变了,可能导致整个布局的变化。

例子:父元素的高度是自动的,他的高度是根据子元素的高度计算而来的,这个在样式计算中是无法体现的,包括控制台Styles 也找不到父元素的高度样式

3.3 布局 - Layout

样式计算有些不会计算宽高,比如说width: 100%或者 width: auto就需要在布局阶段计算;最终产生Layout 树:能找到每个节点的集合信息。被隐藏的元素是找不到几何信息的
在这里插入图片描述

一次遍历DOM树的每个节点,计算节点的几何信息。但并不是所有节点都能被计算几何信息,比如display: none; 找不到几何信息的节点不会出现在Layout树上

注:DOM树和Layout树可能会对不上,比如被隐藏的元素(display:none;)不会出现在 Layout树中;再比如伪元素::before, 这个不会出现在DOM树上,但会出现在布局树上

3.4 分层

主线程有一套自己的分层策略对整个布局树进行分层。
可以通过谷歌浏览器调试工具 右上角三个点—> More tools —> Layers 打开

在这里插入图片描述

优点: 将来一个层改变后,仅会对该层进行后续处理,提升效率。
滚动条、堆叠上下文(z-index)、transform、opacity,等样式可能会影响分层情况,也可以通过will-change属性影响分层结果。
注:这里可以做为优化的手段。如果出现性能问题,发现是分层造成的,可以通过will-change分单独层

3.5 绘制

产生指令集,用于描述如何画,指令完成后,会交给其他线程(合成线程)
注:这里的绘制,是为每一层生成如何绘制的指令,参考canvas的绘制过程的指令,笔移动到哪里,画个什么形状,然后移动到哪里...

到这里为止,渲染主线程工作完成了,剩余步骤交给其他线程完成后续工作

3.6 分块

合成线程对每个图层进行分块,划为为一块块的小区域。他会从线程池红拿取多个线程来完成分块工作。

3.7 光栅化

合成线程将块信息交给GPU 进程,进行光栅化,GPU进程会开启多个线程来完成光栅化,并且优先处理靠近视口区域的块(处理优先级)。
注: 此过程会用到GPU加速
光栅化的结果是画成一块块的位图

3.8 画

合成线程计算出每个位图在屏幕上的位置,交给GPU进程,然后通知硬件进行最终呈现(画出来)。(产生像素点)
注:一些动画,过渡效果,变形效果在这一步才能,
之所以说transform效率高,因为变形发生再合成线程,与渲染主线程无关,这是效率高的本质原因

补充:

  • 渲染进程 包含了渲染主线程和合成线程
  • 渲染进程 是一个沙盒,现实渲染进程遭到攻击不会影响计算机
  • 因为是在沙盒里面无法直接找到硬件,所以需要找GPU进程中转一下产生系统调用 提交给找硬件,完成屏幕成像。

总结:

渲染主线程做的事: parse – style – layout – layer – paint
合成线程做的事: tiling – raster – draw

这里注意下 layout 和 paint
layout 是 布局,paint 是绘制,顺序是 layout 在先,paint在后,接下来看看下面的知识

四、重绘和回流

回流:因为节点增加、删除,节点的尺寸,显示等发生变化产生的重新绘制;会重新生成布局(第三步layout),所以必然会经过绘制(第五步paint),所以回流必会产生重绘

重绘:因为节点的颜色等发生变化产生的重新绘制;因为未发生布局变化(第三步layout ),只引起绘制(第五步paint),所以重绘不会产生回流,呃~感觉有点绝对,网上好像找不到,可能是我搜的有问题,有人给举个例子不

回流(reflow)和重绘(repaint)是浏览器渲染页面时的两个重要概念。 回流是指当 DOM 的变化影响了元素的布局,需要重新计算元素的位置和大小,然后重新构建渲染树,最后进行绘制的过程。回流可能导致一些性能问题,因为它需要计算布局,这是一项非常耗费资源的操作。触发回流的操作包括: - 添加、删除或修改 DOM 元素 - 改变元素的位置、大小 - 改变元素的内容、文字 - 改变窗口大小或滚动 - 修改样式(尤其是影响元素盒模型的样式,例如 width、height、padding、margin 等) 重绘是指当渲染树中的元素样式改变,但没有影响它们的布局时,浏览器只需要重新绘制这些元素的内容,而不需要重新计算它们的位置和大小。重绘回流的开销要小一些,但也需要花费一定的时间。触发重绘的操作包括: - 改变元素的颜色、背景色、边框颜色等 - 改变元素的文本颜色、字体大小等 - 添加、删除、改变元素的阴影、透明度等 因此,为了提高页面性能,我们应该尽可能地减少回流重绘的次数。可以采取的措施包括: - 避免频繁读取和修改 DOM 元素的样式和属性,可以使用缓存或批量修改的方式来优化 - 使用 CSS3 动画代替 JavaScript 实现动画效果,因为 CSS3 动画可以利用硬件加速,而 JavaScript 实现的动画导致频繁的回流重绘 - 将元素的 position 属性设置为 fixed 或 absolute,因为这些元素不影响其他元素的布局,可以减少回流的次数 - 将元素的 opacity 属性设置为 0 或 1,而不是使用 visibility:hidden 或 display:none,因为前者只触发重绘,而后者触发回流
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值