js 和 css 是如何影响DOM树构建的?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js 和 css 是如何影响DOM树构建的?相关的知识,希望对你有一定的参考价值。

大家好,我是coderBin

js 和 css 是如何影响DOM树构建的?

先做个总结,然后再进行具体的分析:

CSS不会阻塞DOM的解析,但是会影响javascript的运行,javaSscript会阻止DOM树的解析,最终css(CSSOM)会影响DOM树的渲染,也可以说最终会影响渲染树的生成。

接下来我们先看javascript对DOM树构建和渲染是如何造成影响的,分成三种类型来讲解:

JavaScript脚本在html页面中

<html>
  <body>
    <div>1</div>
    <script>
      let div1 = document.getElementsByTagName(div)[0]
      div1.innerText = bin
    </script>
    <div>test</div>
  </body>
</html>

两段div中间插入一段JavaScript脚本,这段脚本的解析过程就有点不一样了。

当解析到script脚本标签时,HTML解析器暂停工作,javascript引擎介入,并执行script标签中的这段脚本。

因为这段 javascript 脚本修改了DOM中第一个div中的内容,所以执行这段脚本之后,div节点内容已经修改为 bin 了。脚本执行完成之后,HTML解析器恢复解析过程,继续解析后续的内容,直至生成最终的DOM。

html页面中引入javaScript文件

//foo.js 
let div1 = document.getElementsByTagName(div)[0] 
div1.innerText = bin
<html>
  <body>
    <div>1</div>
    <script type="text/javascript" src=foo.js></script>
    <div>test</div>
  </body>
</html>

这段代码的功能还是和前面那段代码是一样的,只是把内嵌JavaScript脚本修改成了通过javaScript文件加载。

其整个执行流程还是一样的,执行到JAVAScript标签时,暂停整个DOM的解析,执行javascript代码,不过这里执行javascript时,需要现在在这段代码。这里需要重点关注下载环境,因为javascript文件的下载过程会阻塞DOM解析,而通常下载又是非常耗时的,会受到网络环境、javascript文件大小等因素的影响。

优化机制:

谷歌浏览器做了很多优化,其中一个主要的优化就是预解析操作。当渲染引擎收到字节流之后,会开启一个预解析线程,用来分析HTML文件中包含的JavaScript、CSS等相关文件,解析到相关文件之后,会开启一个预解析线程,用来分析HTML文件中包含的javascprit、css等相关文件、解析到相关文件之后,预解析线程会提前下载这些文件。

再回到 DOM 解析上,我们知道引入 JavaScript 线程会阻塞 DOM,不过也有一些相关的策略来规避,比如使用 CDN 来加速 JavaScript 文件的加载,压缩 JavaScript 文件的体积。

另外,如果 JavaScript 文件中没有操作 DOM 相关代码,就可以将该 JavaScript 脚本设置为异步加载,通过 async 或 defer 来标记代码,使用方式如下所示:

<script async type="text/javascript" src=foo.js></script>
<script defer type="text/javascript" src=foo.js></script>

async和defer区别:

  • async:脚本并行加载,加载完成之后立即执行,执行时机不确定,仍有可能阻塞HTML解析,执行时机在load事件派发之前。
  • defer:脚本并行加载,等待HTML解析完成之后,按照加载顺序执行脚本,执行时机DOMContentLoaded事件派发之前。

html页面中有css样式

//theme.css 
div color:blue
<html>
<head>
    <style src=theme.css></style>
</head>
<body>
  <div>1</div>
  <script>
      let div1 = document.getElementsByTagName(div)[0]
      div1.innerText = bin // 需要 DOM
      div1.style.color = red // 需要 CSSOM
  </script>
  <div>test</div>
</body>
</html>

该示例中,JavaScript 代码出现了 div1.style.color = ‘red’ 的语句,它是用来操纵 CSSOM 的,所以在执行 JavaScript 之前,需要先解析 JavaScript 语句之上所有的CSS 样式。所以如果代码里引用了外部的 CSS 文件,那么在执行 JavaScript 之前,还需要等待外部的 CSS 文件下载完成,并解析生成 CSSOM 对象之后,才能执行 JavaScript 脚本。

而 JavaScript 引擎在解析 JavaScript 之前,是不知道 JavaScript 是否操纵了 CSSOM的,所以渲染引擎在遇到 JavaScript 脚本时,不管该脚本是否操纵了 CSSOM,都会执行CSS 文件下载,解析操作,再执行 JavaScript 脚本。所以说 JavaScript 脚本是依赖样式表的,这又多了一个阻塞过程。

总结:通过上面三点的分析,我们知道了 JavaScript 会阻塞 DOM 生成,而样式文件又会阻塞js的执行。


本次的分享就到这里,如果本章内容对你有所帮助的话欢迎点赞+收藏。文章有不对的地方欢迎指出,有任何疑问都可以在评论区留言。希望大家都能够有所收获,大家一起探讨、进步!

以上是关于js 和 css 是如何影响DOM树构建的?的主要内容,如果未能解决你的问题,请参考以下文章

浏览器原理 21 # DOM树:JavaScript是如何影响DOM树构建的?

浏览器如何渲染

由网页渲染提出的优化建议

dom渲染(repaint/reflow)

影响浏览器重绘和重排

htmlcssjs三者的加载顺序