写点什么

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

作者:CoderBin
  • 2022-10-19
    广东
  • 本文字数:2173 字

    阅读完需:约 1 分钟

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

前言

大家好,我是 coderBin,本文将讲解关于 js 和 css 是如何影响 DOM 树构建的,相信看完本文的同学会有所收获,谢谢


面试官系列文章

【1】面试官:你说说 js 中实现继承有哪几种方法?

【2】面试官:说说你对事件循环的理解

高频面试总结

【1】75道关于CSS的高频面试题总结,请注意查收!🔥

【2】关于Vue的一些高频面试题总结

首先

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


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 的执行。

往期推荐 💐 🌸 🌹 🌻 🌺 🍁

高阅读好文


【1】关于Vue的一些高频面试题总结


【2】75道关于CSS的高频面试题总结,请注意查收!🔥


【3】Vue内置指令大全


【4】面试官:你说说 js 中实现继承有哪几种方法?


【5】一篇文章带你搞懂 this 的四个绑定规则 ✍


【6】MongoDB 基础入门到后端接口开发进阶实战!


----- 🌻 查看全部 🍁 -----




每文一句:每一日所付出的代价都比前一日高,因为你的生命又消短了一天,所以每一日都要更积极。今天太宝贵,不应该为酸苦的忧虑和辛涩的悔恨所销蚀,抬起下巴,抓住今天,它不再回来。


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

发布于: 刚刚阅读数: 4
用户头像

CoderBin

关注

不念过往,不惧将来 2020-10-14 加入

普通人只考虑他们将如何度过时间,而有智慧的人则试图利用时间 — CoderBin

评论

发布
暂无评论
js 和 css 是如何影响DOM树构建的?_CSS_CoderBin_InfoQ写作社区