DOM渲染与优化 - CSS、JS、DOM解析和渲染阻塞问题

文章目录

  • DOM渲染
    • 面试题
    • DOM的渲染过程
      • DOM渲染的时机与渲染进程的概述
      • 浏览器的渲染流程
        • 1. 解析HTML生成DOM树:遇到`<img>`标签加载图片
        • 2. 解析CSS生成CSSOM(CSS Object Model): 遇见背景图片链接不加载
        • 3. 将DOM树和CSSOM树合并生成渲染树:加载可视节点的背景图片
        • 4. 遍历渲染树开始布局,计算每个节点的位置大小等信息,输出包含DOM元素样式和位置的布局树。
        • 5. 绘制:开始渲染图片
        • 6. 合成: 已绘制的不同图层合并成在一起,输出到屏幕。
      • CSS、JS、DOM解析和渲染阻塞问题
        • JS加载阻塞DOM渲染问题,怎么解决? - 异步JS,JS三种异步加载的方式
          • script 标签中的 async 和 defer 属性
        • DOMContentLoaded和Load
    • DOM渲染优化

DOM渲染

面试题

  • js的DOM渲染是单线程的,那渲染的过程是什么样的?浏览器渲染页面的过程?
  • script标签,包含async属性的script标签,包含defer属性的script标签对文档渲染有啥影响?
  • css是否阻塞页面的解析和渲染?css渲染会不会阻塞dom渲染,会不会阻塞dom树建立
  • js会阻塞dom渲染吗,图片加载会阻塞dom渲染吗?
  • Dom渲染是在事件循环机制哪里实现的
  • JS加载阻塞DOM渲染问题,怎么解决
  • 生成DOM树和CSSOM树之后怎么生成渲染树

DOM的渲染过程

DOM渲染的时机与渲染进程的概述

DOM的渲染将HTML,CSS,JS等资源后,解析-构建树-绘制,最后呈现给用户能看到的界面的这个过程。
页面的渲染,JS的执行,事件的触发都是在渲染进程中进行的。

渲染进程包含多个线程

  • JS引擎线程:JavaScript引擎V8,负责处理JavaScript脚本程序。

为什么js是单线程的,假如JS是多线程的,假设现在有2条线程,一条在dom节点上添加节点,另一条删除这个节点。

  • GUI 渲染线程: 负责渲染浏览器界面,解析 HTML,CSS,构建render树,布局和绘制等。

GUI 渲染线程与 JS 引擎线程是互斥的,当 JS 引擎执行时 GUI 线程会被挂起,GUI 更新会被保存在一个队列中等到 JS 引擎空闲时立即被执行。

  • 事件触发线程: 控制事件循环,当对应的事件符合条件被触发时,该线程会将事件添加到待处理的事件队列中,等待JS引擎的处理。
  • 定时器触发线程:当使用setTimeout或者setInterval时,需要定时器线程计时。计时完成后会将特定的事件推进事件触发线程的任务队列中,等待进入主线程执行。
  • 异步http请求线程:XMLHttpRequest在连通后通过浏览器新起一个线程请求。检测到状态变化时,如果有设置回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中,再由JS引擎执行。

渲染进程的创建时机
每次新开一个标签页,都会创建一个新的渲染进程。
但有例外,比如从A页面里面打开一个新的页面B页面,而A页面和B页面又属于同一站点的话,A和B就共用一个渲染进程。

浏览器的渲染流程

1. 解析HTML生成DOM树:遇到<img>标签加载图片

在这里插入图片描述DOM树的结构可以通过document打印查看,DOM结构,DOM和HTML内容几乎是一样的,但是和HTML不同的是,DOM是保存在内存中树状结构,可以通过JavaScript来查询或修改其内容。
这个过程中,display:none的元素、script标签、注释也都会添加到DOM树中。

2. 解析CSS生成CSSOM(CSS Object Model): 遇见背景图片链接不加载

3. 将DOM树和CSSOM树合并生成渲染树:加载可视节点的背景图片

渲染树中只包含渲染可见的节点
从DOM树的根节点开始向下遍历每个子节点,忽略所有不可见的节点,比如display:nonehead标签。在CSSOM中为每个可见的子节点找到对应的规则并应用。

4. 遍历渲染树开始布局,计算每个节点的位置大小等信息,输出包含DOM元素样式和位置的布局树。

第一次确定节点大小和位置称为布局,之后重新触发页面布局可以称为回流

5. 绘制:开始渲染图片

遍历布局树进行分层,生成分层树后,为每个图层分别进行绘制,在绘制中不同的图层渲染互不影响。

在这里插入图片描述
如果一个节点没有对应的层,那么这个节点就从属于父节点的图层。

渲染引擎为特点的节点创建新的层

  1. 拥有层叠上下文属性的元素会被提升为单独一层
    2. 在这里插入图片描述
    比如非static的positionz-indexfilteropacity

  2. 需要剪裁(clip)的地方也会被创建为图层。

6. 合成: 已绘制的不同图层合并成在一起,输出到屏幕。

这个阶段可以开启GPU加速
在这里插入图片描述
所以图片加载不会阻塞DOM渲染

CSS、JS、DOM解析和渲染阻塞问题

概念

  1. DOM解析 :浏览器向服务器请求到了 HTML 文档后便开始解析,产物是 DOM(文档对象模型),到这里 HTML 文档就被加载和解析完成了。 DOM的解析就是生成DOM树的过程
  2. DOM渲染:浏览器是解析DOM生成DOM Tree,结合CSS生成的CSS Tree,最终组成render tree,再渲染页面的过程。

结论

  • async/defer的JS执行(同步的JS执行)会阻塞DOM的解析过程
    GUI 渲染线程与 JavaScript 引擎为互斥,当 JS 引擎执行时 GUI 线程会被挂起。直到 JS 程序一轮调度执行完成,才会接着执行。因此如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

  • CSS不会阻塞DOM的解析,但会阻塞DOM的渲染

DOM解析和CSS解析是两个并行的进程,所以CSS本身不会阻塞DOM的解析
通过JS间接影响 CSS加载会阻塞后面的JS语句执行 --> JS语句阻塞DOM的解析

  • CSS加载会阻塞后面的JS语句执行
    GUI 渲染线程与 JavaScript 引擎为互斥

补充知识1:浏览器解析DOM时,虽然会一行一行向下解析,但是它会预先同时加载具有引用标记的外部资源(例如带有src标记的<script>标签),而在解析到此标签时,则无需再去加载,直接运行,以此提高运行效率。
补充知识2:浏览器无法预先知道脚本的具体内容,因此在碰到<script>标签时,会触发页面渲染,确保<script>脚本内能获取到DOM的最新的样式。

JS加载阻塞DOM渲染问题,怎么解决? - 异步JS,JS三种异步加载的方式

defer、async 仅仅是改变脚本的执行时机

JS三种异步加载的方式

方式执行时机执行顺序
type="module"浏览器加载 ES6 模块,整个页面解析完毕,再执行模块脚本。等同于defer属性使用相同的执行队列,谁在前面谁先执行。
script标签中defer属性页面解析完毕再执行如果有多个defer脚本,会按照它们在页面出现的顺序加载。放入队列中,先进先出。
script标签中async属性脚本下载完,渲染线程就会中断渲染,执行这个脚本以后,再继续渲染而多个async脚本是不能保证加载顺序的
script 标签JS 执行顺序是否阻塞解析 HTML
<script>在 HTML 中的顺序阻塞
<script async>网络请求返回顺序可能阻塞,也可能不阻塞
<script defer>在 HTML 中的顺序不阻塞
script 标签中的 async 和 defer 属性

渲染进程在解析 HTML 的时候,如果遇到一个没有任何属性的 script 标签,就会暂停解析,先发送网络请求获取该 JS 脚本的代码内容,然后让 JS 引擎执行该代码,当代码执行完成后再切换回渲染引擎继续渲染流程。
在这里插入图片描述
async、defer属性的js脚本,渲染引擎遇到这一行命令,就会开始下载脚本,同时直接执行后面的命令。

async脚本会在JS下载完毕后立即执行
假设此时HTML没有解析完,会暂停渲染,先让JS引擎执行代码,执行完毕后再切换回渲染引擎继续渲染流程。
在这里插入图片描述
HTML 解析完了之后,async脚本才加载完,然后再执行脚本
在这里插入图片描述
defer会等HTML加载解析完再执行
defer的优先级高于DOMContentLoaded事件。页面渲染完毕后先执行defer属性的脚本,再触发DOMContentLoaded事件。
在这里插入图片描述

DOMContentLoaded和Load

对于浏览器说,页面加载主要有两个事件

  • DOMContentLoaded: 就是当页面的内容解析完成后(页面DOM加载完成就触发),则触发该事件
  • Load:等待页面的所有资源都加载完成才会触发,这些资源包括css、js、图片视频

DOM渲染优化

从重绘和回流方面进行优化

  • 开启GPU加速
    • transform
    • opacity
    • will-change
  • JS优化
    • 对于 scroll 等事件进行防抖/节流处理。
    • 使用变量缓存对敏感属性值(offset等)的计算
    • 避免频繁改动使用style,采用修改class的方式

从其他渲染阶段

  • 使用Web Worker开启多线程,将纯计算的工作迁移到Web Worker上处理(防止js执行事件过程阻塞页面渲染)。
  • 使用CDN获取css等静态资源(加快css的加载速度)
  • 避免动画实现中丢帧造成卡顿现象,尽量不用计时器实现动画,而采用window.requestAnimationFrame(回调)

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows mysql8.0主从配置

windows mysql8.0主从配置 一、安装两个MySQL并配置 1. 主库配置my.ini&#xff0c;我的主库是安装版 [mysqld] # 设置mysql的安装目录 basedirD:\\soft\\mysql-5.7.39 # 设置mysql数据库的存放目录 datadirD:\\soft\\mysql-5.7.39\\data #设置3306端口 port3306 #主服务器…

SAP ABAP基础知识 访问外部数据库-开发篇

前言 本文主要介绍通过ABAP语言访问外部数据库的几种方式 一、外部数据库配置 本文示例中的代码访问了两个外部数据库 MTD : 外部oracle数据库,其中示例表 ZTTEMP 字段( ZZTNO,WERKS) S4Q : 外部HANA数据库(开发系统访问测试系统的数据库), 使用表USR02,ZTTEMP 二、ABAP访问…

HBS 家庭总线驱动和接收芯片MS1192,应用于电话及相关设备、空调设备、安全设备、AV 装置

MS1192 是适用于 HBS 总线规范&#xff08;日本电子工业协会&#xff09; 的适配器芯片&#xff0c;具备发送、接收数据的功能。在发送接收 单元中&#xff0c;采用 AMI 编码方式&#xff0c;可使用双绞线进行互联&#xff0c;信 号传输采用差分方式。 芯片采用单电源…

MFC-GetAdaptersAddresses获取网卡信息

需要:#pragma comment(lib, "IPHLPAPI.lib") GetAdaptersAddresses函数参数说明 ULONG bufferSize = 0;ULONG result = ::GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &bufferSize);/*参数1:ULONG Family 网络协议族,此参…

CG MAGIC分享3ds Max卡顿未保存处理方法有哪些?

3ds Max进行建模、渲染这一系列过程中&#xff0c;大家使用中都会遇到各种原因导致软件卡顿或崩溃是很常见的情况。 可以说卡机没关系&#xff0c;可是卡顿发生时&#xff0c;如果之前的工作没有及时保存&#xff0c;可能会导致数据的丢失和时间的浪费。这就是最让人烦躁的了&…

iframe 实现跨域,两页面之间的通信

一、 背景 一个项目为vue2&#xff0c;一个项目为vue3&#xff0c;两个不同的项目实现iframe嵌入&#xff0c;并实现通信 二、方案 iframe跨域时&#xff0c;iframe组件之间常用的通信&#xff0c;主要是H5的possmessage方法 三、案例代码 父页面-vue2&#xff08;端口号为…

《PostgreSQL数据分区:原理与实战》

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f405;&#x1f43e;猫头虎建议程序员必备技术栈一览表&#x1f4d6;&#xff1a; &#x1f6e0;️ 全栈技术 Full Stack: &#x1f4da…

vue基础知识十:Vue中组件和插件有什么区别?

一、组件是什么 回顾以前对组件的定义&#xff1a; 组件就是把图形、非图形的各种逻辑均抽象为一个统一的概念&#xff08;组件&#xff09;来实现开发的模式&#xff0c;在Vue中每一个.vue文件都可以视为一个组件 组件的优势 降低整个系统的耦合度&#xff0c;在保持接口不…

DatasetDM: Synthesizing Data with Perception Annotations Using Diffusion Models

论文作者&#xff1a;Weijia Wu,Yuzhong Zhao,Hao Chen,Yuchao Gu,Rui Zhao,Yefei He,Hong Zhou,Mike Zheng Shou,Chunhua Shen 作者单位&#xff1a;Zhejiang University; University of Chinese Academy of Sciences; National University of Singapore 论文链接&#xff1…

睿趣科技:抖音开店前期需要准备什么

抖音作为全球最受欢迎的短视频平台之一&#xff0c;已经成为了许多年轻人的创业和赚钱的机会。如果你计划在抖音上开店&#xff0c;那么在正式开业之前&#xff0c;有一些重要的准备工作是必不可少的。下面就是抖音开店前期需要准备的关键步骤和注意事项。 确定你的目标和产品&…

2023年浦东新区数字化安全风险智慧管控技能比武初赛-技能题一

目录 二、技能题 2.1 MD5===MD5 三、业*&&&务**&&联&&&*&&系 二、技能题 2.1 MD5===MD5

C++多线程的用法(包含线程池小项目)

一些小tips: 编译命令如下&#xff1a; g 7.thread_pool.cpp -lpthread 查看运行时间&#xff1a; time ./a.out 获得本进程的进程id&#xff1a; this_thread::get_id() 需要引入的库函数有&#xff1a; #include<thread> // 引入线程库 #include<mutex> //…