四、浏览器渲染过程,DOM,CSSDOM,渲染,布局,绘制详细介绍

news2024/11/27 15:41:23
知识点:
1、为什么不能先执行 js文件??
我们不能先执行JS文件,必须等到CSSOM构建完成了才能执行JS文件,因为前面已经说过渲染树是需要DOM和CSSOM构建完成了以后才能构建,而且JS是可以操控CSS样式的,所以这一步就是解析CSS文件并且构建CSSOM
2、DOM和CSSOM不同之处??
CSSOME的构建就是渲染中一个重要的阻塞因素,其实DOM也是会阻塞渲染过程,毕竟没有DOM,网页的框架都建造不起来,但是DOM有一点好处,就是可以部分解析,而CSSOM不能部分解析
3、 为什么DOM可以部分解析,CSSOM却不能?
比如我们给body设置了字体为32px,然后我们又给body里面的div设置了字体为16px,如果CSSOM只解析了body,后面的div没有解析或者延迟解析,那就会乱套了,所以CSSOM不能进行部分解析

在这里插入图片描述

4、渲染HTML+css+javascript

在这里插入图片描述
不过在解析CSS文件并且构建CSSOM的时候,浏览器依旧可以去下载并且解析JS文件,等CSSOM构建完成以后就可以执行JS里的内容了,不过大家有没有发现HTML的解析刚刚就停止了,原因可能很多同学都知道了,因为JS是会阻塞HTML解析的,虽然看起来JS并没有直接阻塞渲染的过程,但是有间接的影响因为JS既可以操作DOM,又可以操作CSSOM如果不等JS下载解析执行完以后再构建DOM,那有可能会导致网页的有些内容出现了又消失,所以在解析HTML的时候,不管是行内JS代码还是外部JS文件,都会让HTML的解析停止下来,虽然DOM是可以部分解析的,但是对于这个网页来说就相当于阻塞了第一次的渲染,JS执行完成之前什么内容都没有,JS执行完之后什么都正常了,也就是形成渲染树(构建DOM后),进行布局,最后绘制
在这里插入图片描述

疑问???:

DOM 树,执行一行,构建一行,最终js的执行(也需要看js的位置),需要等CSSDOM都执行完

疑问?1、Dom树构建完成,javascript执行中可以获取dom嘛,还没有渲染阶段?

解答:1)、js文件在head中引入,获取不到当前的DOM,更不能操作DOM,因为DOM树还没有构建完成。
2)、js文件在body中引入,可以操作DOM,因为js执行之前DOM树中的 《p》 标签构建完成,CSSDOM构建完成,

疑问?2、获取远程的js文件,延迟会阻塞html的渲染,请求回来会解析js文件,但不会执行js文件,需要等CSSDOM解析构建完成,就可以执行js文件,等js文件执行完,就开始构建DOM树,最后布局跟绘制

1)、js文件执行会阻塞HTML的DOM 树构建,也会阻塞 DOM + CSSDOM 渲染(js文件在head阻塞,js文件在body文件后不会阻塞)
2)、js 跟 css 文件,看服务器谁返回的快,就先解析哪个,但是js文件执行,需要等CSSDOM解析、构建完成((因为style文件是pink,style1是green,不可能让屏幕一闪一闪的))
3)、js文件在head标签中引入,是无法操作DOM的,因为DOM还没渲染
4)、
( js文件跟css文件解析看服务器返回的资源,哪个时间快先解析哪个,但是js文件不会执行)js文件会阻止 DOM 构建,但是js的执行需要等 CSSDOM 构建完成,执行js文件(如果文件放在html页面的顶端)是无法获取DOM的,

疑问?3、js文件执行过程中,可以操作DOM嘛?

可以,具体看 js文件的位置,如果在 head标签中,不可以,DOM还没有构建,如果js文件在body中,p标签之后,那么可以操作DOM

<!DOCTYPE html>
<html lang="en">
<head>
  <!-- <link href="/style1.css" rel="stylesheet" type="text/css"> -->
  <!-- <script src="/settingPage.js"></script> -->
  <link href="/style.css" rel="stylesheet" type="text/css">
  <title>浏览器请求的HTML资源</title>
  <!-- 疑问1 疑问3?可以操作DOM吗?
    1、在此处引入js文件,开始解析、执行,会阻塞HTML中DOM树构建
    2、在head引入js文件不能操作DOM,因为构建DOM树被阻塞了
    3、js执行,阻塞 DOM、CSSDOM 树的构建,具体看实际情况,如果在 p 标签之后在执行js文件,那么页面已经开始渲染了,在head中执行js文件,肯定是要等 CSSDOM 构建完成,才会执行(因为style文件是pink,style1是green,不可能让屏幕一闪一闪的)
    4、不可以操作DOM,因为 p 标签还没有构建
  -->
  <!-- <script src="/settingPage.js"></script>
  <link href="/style2.css" rel="stylesheet" type="text/css"> -->
</head>
<body>
  <p id="ppp">Hello <span>web performance</span>students!<p>
  <!-- <div><img src="awesome-photo.jpg"></div> -->

  <!-- 疑问2 ?
    1、js文件执行过程中,DOM树 p 标签构建完成,CSSDOM也构建完成,不影响页面 DOM树的构建跟渲染(因为js会阻塞DOM树构建,DOM树可以解析一部分,构建一部分),
   -->
  <script src="/settingPage.js"></script>
  <!-- 疑问4 ?
     CSS 跟 js代码,js在后,js执行最终的样式, 
      js在 P标签之前,获取不到DOM。
      比如: <p id="ppp" style="display:none;"></p>
      <script>
          const elm = document.getElementById('ppp')
          elm.style.display = 'block'
          elm.style.background = '#000'
      </script>
   -->
</body>
</html>

疑问?4、渲染树中设置标签display:none,js代码中删除style,会怎么执行?

CSS 跟 js代码,js在后,js执行最终的样式,
js在 P标签之前,获取不到DOM。

  比如: <p id="ppp" style="display:none;"></p>
  <script>
      const elm = document.getElementById('ppp')
      elm.style.display = 'block'
      elm.style.background = '#000'
  </script>

一、页面加载过程(请看第一篇文章,浏览器输入URL会发生什么)

在介绍浏览器渲染过程之前,我们简明扼要介绍下页面的加载过程,有助于更好理解后续渲染过程。

要点如下:

  • 浏览器根据 DNS 服务器得到域名的 IP 地址
  • 向这个 IP 的机器发送 HTTP 请求
  • 服务器收到、处理并返回 HTTP 请求
  • 浏览器得到返回内容

例如在浏览器输入https://baidu.com,然后经过 DNS 解析,baidu.com对应的 IP 是36.36.36.36(不同时间、地点对应的 IP 可能会不同)。然后浏览器向该 IP 发送 HTTP 请求。
服务端接收到 HTTP 请求,然后经过计算(向不同的用户推送不同的内容),返回 HTTP 请求,返回的文件内容如下,以HTML举例:
(整个页面:HTML/XHTML/SVG、样式:CSS、功能性代码:JavaScript)
在这里插入图片描述
其实就是一堆 HMTL 格式的字符串,因为只有 HTML 格式浏览器才能正确解析,这是 W3C 标准的要求。接下来就是浏览器的渲染过程。

二、浏览器渲染过程

比如,对于这段代码,如何解析,生成DOM树🌲🌲🌲

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="style.css" rel="stylesheet">
    <title>Critical Path</title>
  </head>
  <body>
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg"></div>
  </body>
</html>

2.1、解析(就好建房子,画框架图)

在这里插入图片描述

在这里插入图片描述

1)、Bytes—>Characters过程:浏览器从磁盘或网络读取HTML的原始字节,并根据文件的指定编码(例如 UTF-8)将它们转换成字符串。**;

2)、Tokens过程:将字符串转换成Token,例如:、等。Token中会标识出当前Token是“开始标签”或是“结束标签”亦或是“文本”等信息。**

疑问? 这时候你一定会有疑问,节点与节点之间的关系如何维护?

事实上,这就是Token要标识“起始标签”和“结束标签”等标识的作用。例如“title”Token的起始标签和结束标签之间的节点肯定是属于“head”的子节点。
在这里插入图片描述
上图给出了节点之间的关系,例如:“Hello”Token位于“title”开始标签与“title”结束标签之间,表明“Hello”Token是“title”Token的子节点。同理“title”Token是“head”Token的子节点。

3)、Nodes根据token序列分析语法,得到一个个节点node;**

2.2、根据node序列,分析并构建DOM树(建房子,框架模型已生成)。

事实上,构建DOM的过程中,不是等所有Token都转换完成后再去生成节点对象,而是一边生成Token一边消耗Token来生成节点对象。换句话说,每个Token被生成后,会立刻消耗这个Token创建出节点对象。注意:带有结束标签标识的Token不会创建节点对象。

在这里插入图片描述

2.3、 构建CSSOM树(构建CSSOM的过程与构建DOM的过程非常相似)---- (建房子,装饰材料,油漆,板砖,门)

当浏览器接收到一段CSS,浏览器首先要做的是识别出Token,然后构建节点并生成CSSOM。
在这里插入图片描述

在这一过程中,浏览器会确定下每一个节点的样式到底是什么,并且这一过程其实是很消耗资源的。因为样式你可以自行设置给某个节点,也可以通过继承获得。在这一过程中,浏览器得递归 CSSOM 树,然后确定具体的元素到底是什么样式。
注意:CSS匹配HTML元素是一个相当复杂和有性能问题的事情。所以,DOM树要小,CSS尽量用id和class,千万不要过渡层叠下去。

假如somestyle.css文件的内容如下:

body { font-size: 16px }
p { font-weight: bold }
span { color: red }
p span { display: none }
img { float: right }

1)、根据node序列,生成DOM树。

在这里插入图片描述

2.4、构建渲染树(当我们生成 DOM 树和 CSSOM 树以后,就需要将这两棵树组合为渲染树。)-----(渲染后还不能渲染,只是图纸有了,需要买多少砖,搬砖,门,窗户)

在这里插入图片描述

在这一过程中,不是简单的将两者合并就行了。渲染树只会包括需要显示的节点和这些节点的样式信息,如果某个节点是 display: none 的,那么就不会在渲染树中显示。

疑问?浏览器如果渲染过程中遇到JS文件怎么处理?

1、渲染过程中,如果遇到 script标签 就停止渲染,执行 JS 代码。因为浏览器有GUI渲染线程与JS引擎线程,为了防止渲染出现不可预期的结果,这两个线程是互斥的关系。
2、JavaScript的加载、解析与执行会阻塞DOM的构建,也就是说,在构建DOM时,HTML解析器若遇到了JavaScript,那么它会暂停构建DOM,将控制权移交给JavaScript引擎,等JavaScript引擎运行完毕,浏览器再从中断的地方恢复DOM构建。
3、也就是说,如果你想首屏渲染的越快,就越不应该在首屏就加载 JS 文件,这也是都建议将 script 标签放在 body 标签底部的原因。当然在当下,并不是说 script 标签必须放在底部,因为你可以给 script 标签添加 defer 或者 async 属性(下文会介绍这两者的区别)。

疑问?JS文件不只是阻塞DOM的构建,它会导致CSSOM也阻塞DOM的构建。

原本DOM和CSSOM的构建是互不影响,井水不犯河水,但是一旦引入了JavaScript,CSSOM也开始阻塞DOM的构建,只有CSSOM构建完毕后,DOM再恢复DOM构建。
这是什么情况?
这是因为JavaScript不只是可以改DOM,它还可以更改样式,也就是它可以更改CSSOM。因为不完整的CSSOM是无法使用的,如果JavaScript想访问CSSOM并更改它,那么在执行JavaScript时,必须要能拿到完整的CSSOM。所以就导致了一个现象,如果浏览器尚未完成CSSOM的下载和构建,而我们却想在此时运行脚本,那么浏览器将延迟脚本执行和DOM构建,直至其完成CSSOM的下载和构建。也就是说,在这种情况下,浏览器会先下载和构建CSSOM,然后再执行JavaScript,最后在继续构建DOM。

2.4 布局 (布局完成后,开始建房子,搭建主体,留门框,窗口)

在这里插入图片描述

2.5 绘制(把渲染树以像素的形式绘制在页面)

在这里插入图片描述

文章引出以下几点

1.async和defer的作用是什么?有什么区别?

2.为什么操作 DOM 慢

  • 把 DOM 和 JavaScript 各自想象成一个岛屿,它们之间用收费桥梁连接。——《高性能 JavaScript》 JS 是很快的,在

  • JS 中修改 DOM 对象也是很快的。在JS的世界里,一切是简单的、迅速的。但 DOM 操作并非 JS

  • 一个人的独舞,而是两个模块之间的协作。 因为 DOM 是属于渲染引擎中的东西,而 JS 又是 JS 引擎中的东西。当我们用 JS 去操作

  • DOM 时,本质上是 JS 引擎和渲染引擎之间进行了“跨界交流”。这个“跨界交流”的实现并不简单,它依赖了桥接接口作为“桥梁”(如下图)。
    在这里插入图片描述

  • 过“桥”要收费——这个开销本身就是不可忽略的。我们每操作一次

  • DOM(不管是为了修改还是仅仅为了访问其值),都要过一次“桥”。过“桥”的次数一多,就会产生比较明显的性能问题。因此“减少 DOM 操作”的建议,并非空穴来风。

3.你真的了解回流和重绘吗

4、性能优化策略

引用以下文章:

1、作者:浪里行舟文章地址
2、作者:读行笔记文章地址
3、作者:技术蛋老师 B站视频地址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1052832.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java 进阶篇】深入理解 JDBC:Java 数据库连接详解

数据库是现代应用程序的核心组成部分之一。无论是 Web 应用、移动应用还是桌面应用&#xff0c;几乎都需要与数据库交互以存储和检索数据。Java 提供了一种强大的方式来实现与数据库的交互&#xff0c;即 JDBC&#xff08;Java 数据库连接&#xff09;。本文将深入探讨 JDBC 的…

Linux系统编程(七):线程同步

参考引用 UNIX 环境高级编程 (第3版)黑马程序员-Linux 系统编程 1. 同步概念 所谓同步&#xff0c;即同时起步、协调一致。不同的对象&#xff0c;对 “同步” 的理解方式略有不同 设备同步&#xff0c;是指在两个设备之间规定一个共同的时间参考数据库同步&#xff0c;是指让…

从 低信噪比陆上地震记录 解决办法收集 到 走时层析反演中的折射层析调研

目录 (前言1) 关于背景的回答:(前言2) 现有的降低噪声, 提高信噪比的一些特有方法的论文资料 (传统策略):1. 关于波形反演与走时层析反演2. 折射层析3. 用一个合成数据来解释折射层析反演的思路4. 其他层析反演方法:5. 关于层析反演的一些TIPS (可补充)参考文献: 降噪有关资料参…

ElementUI之CUD+表单验证

目录 前言&#xff1a; 增删改查 表单验证 前言&#xff1a; 继上篇博客来写我们的增删改以及表单验证 增删改查 首先先定义接口 数据样式&#xff0c;我们可以去elementUI官网去copy我们喜欢的样式 <!-- 编辑窗体 --><el-dialog :title"title" :visib…

国庆《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书行将售罄

国庆《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书行将售罄 国庆《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书行将售罄

leetcode-----二叉树习题

目录 前言 1. 二叉树的中序遍历 2. 相同的树 3. 二叉树的最大深度 4. 二叉树的最小深度 5.二叉树的前序遍历 6. 二叉树的后序遍历 7. 对称二叉树 前言 前面我们学习过了二叉树的相关知识点&#xff0c;那么今天我们就做做练习&#xff0c;下面我会介绍几道关于二叉树的…

如何实现一个业务系统的自动化框架搭建

1、框架结构 我在该项目采用的是关键字驱动测试的框架类型。首先创建如下几个目录common&#xff08;公共模块&#xff09;、config&#xff08;公共配置&#xff09;、logs&#xff08;运行日志&#xff09;、reports&#xff08;测试报告&#xff09;、resources&#xff08…

前端的多种克隆方式和注意事项

克隆的意义和常见场景: 意义: 保证原数据的完整性和独立性常见场景: 复制数据, 函数入参, class构造函数等 浅克隆: 对象常用的浅克隆 es6扩展运算符...Object.assign 数组常用的浅克隆 es6的扩展运算符...slice>arr.slice(0)[].concat 深度克隆: 克隆对象的每个层级如…

YOLOv8改进算法之添加CA注意力机制

1. CA注意力机制 CA&#xff08;Coordinate Attention&#xff09;注意力机制是一种用于加强深度学习模型对输入数据的空间结构理解的注意力机制。CA 注意力机制的核心思想是引入坐标信息&#xff0c;以便模型可以更好地理解不同位置之间的关系。如下图&#xff1a; 1. 输入特…

【RocketMQ】【源码】Dledger日志复制源码分析

消息存储 在 【RocketMQ】消息的存储一文中提到&#xff0c;Broker收到消息后会调用CommitLog的asyncPutMessage方法写入消息&#xff0c;在DLedger模式下使用的是DLedgerCommitLog&#xff0c;进入asyncPutMessages方法&#xff0c;主要处理逻辑如下&#xff1a; 调用serial…

leetCode 122.买卖股票的最佳时机 II 动态规划 + 状态转移 + 状态压缩

122. 买卖股票的最佳时机 II - 力扣&#xff08;LeetCode&#xff09; 给你一个整数数组 prices &#xff0c;其中 prices[i] 表示某支股票第 i 天的价格。 在每一天&#xff0c;你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买&…

006:连续跌三天,第四天上涨的概率--用python统计

我们已经可以获取到K线信息了&#xff0c;然后我们来进行一些统计&#xff0c;就统计连续三天下跌&#xff0c;第四天上涨的概率。 我们用宁波银行&#xff08;002142&#xff09;最近三年的数据来统计。先用上一篇的程序下载到K线数据&#xff0c;得到文件002142.csv。然后在…

Spring修炼之旅(4)静态/动态代理模式与AOP

一、代理模式概述 代理模式 为什么要学习代理模式&#xff0c;因为AOP的底层机制就是动态代理&#xff01; 代理模式&#xff1a; 静态代理 动态代理 学习aop之前 , 我们要先了解一下代理模式&#xff01; 1.1静态代理 静态代理角色分析 抽象角色 : 一般使用接口或者抽象…

【数据结构练习】二叉树相关oj题集锦二

目录 前言 1.平衡二叉树 2.对称二叉树 3.二叉树遍历 4.层序遍历 5.判断一棵树是不是完全二叉树 前言 编程想要学的好&#xff0c;刷题少不了&#xff0c;我们不仅要多刷题&#xff0c;还要刷好题&#xff01;为此我开启了一个弯道超车必做好题锦集的系列&#xff0c;此为…

2023/9/30 使用消息队列完成进程间通信

发送方 ​ #include <myhead.h> //消息结构体 typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }Msg_ds;#define SIZE sizeof(Msg_ds) - sizeof(long) //正文大小 int main(int argc, const char *argv[]) {//1.创建key值key_t key ;if((key …

中断向量控制器(NVIC)

1. 什么是中断 在处理器中&#xff0c;中断是一个过程&#xff0c;即CPU在正常执行程序的过程中&#xff0c;遇到外部/内部的紧急事件需要处理&#xff0c;暂时中止当前程序的执行&#xff0c;转而去为处理紧急的事件&#xff0c;待处理完毕后再返回被打断的程序处继续往下执行…

Spring MVC 中的国际化和本地化

Spring MVC 中的国际化和本地化 国际化&#xff08;Internationalization&#xff0c;简称i18n&#xff09;和本地化&#xff08;Localization&#xff0c;简称l10n&#xff09;是构建多语言应用程序的重要概念。Spring MVC提供了丰富的支持&#xff0c;使开发人员能够轻松地处…

Python 笔记06(Mysql数据库)

一 基础 1.1 安装 MySQL下载参考&#xff1a;MySQL8.0安装配置教程【超级详细图解】-CSDN博客 测试是否安装并正确配置环境变量&#xff1a; 1.2 查看服务器是否正常运行 1.3 显示数据库 show databases; 1.4 退出 exit 1.5 python 连接 1.6 查主机IP ipconfig

2.springboot代理调用

1.概述 本文介绍在方法上开启声明式事务Transactional后(使用InfrastructureAdvisorAutoProxyCreator创建jdk动态代理)&#xff0c;springboot的调用该方法的过程&#xff1b; 2.结论(重点) 在方法开启声明式事务后&#xff0c;spring会为该对象创建动态代理。spring容器为该…

Android Jetpack组件架构:ViewModel的原理

Android Jetpack组件架构&#xff1a;ViewModel的原理 导言 本篇文章是关于介绍ViewModel的&#xff0c;由于ViewModel的使用还是挺简单的&#xff0c;这里就不再介绍其的基本应用&#xff0c;我们主要来分析ViewModel的原理。 ViewModel的生命周期 众所周知&#xff0c;一般…