美文网首页
16.1、时间线、解析与渲染、封装文档解析完毕函数

16.1、时间线、解析与渲染、封装文档解析完毕函数

作者: 一土二月鸟 | 来源:发表于2020-06-10 23:04 被阅读0次

浏览器渲染页面的过程

  • 当网页被下载下来后,开始解析html文档,把需要用到的资源进行下载
  • 当遇到script时,会同步下载,并执行完script中的代码后,开始下载之后的资源,js会阻断domtree的构建。当同步的js全部执行完,domtree构建完后,DOMContentLoaded才会被触发。
  • 当遇到样式link时,会异步下载,不会影响其他文件的下载,但在加载结束前,会阻断其后面js的执行。css不会直接影响domtree的构建,但是会影响页面的渲染。css加载结束之前,浏览器不会将其后面的元素渲染到页面
  • 除了script和css以外,其余的资源如图片等,都属于异步加载,并对其他元素没有任何影响,当所有资源加载完毕后,会触发onload事件。

window.onload

  • window.onload要等到页面解析完成,包括dom tree构建、cssom构建、render tree构建完毕,页面渲染完毕,页面中所需的资源全部加载完毕后,开始执行。
<body>
<div>0</div>
<script type="text/javascript">
  document.write(1);
</script>
</body>
页面呈现 0 和 1  
原因:<script>属于dom tree的一部分,在构建dom tree未构建结束时,
会将document.write输出的元素追加到已有元素的后面。
<div>0</div>
<script type="text/javascript">
  window.onload = function () {
    document.write(1)
  }
</script>
页面呈现 1  
window.onload是在页面全部加载完毕后执行,此时document.write相当于是在覆盖整个dom tree

页面渲染的过程

老浏览器,http请求回来页面后:
1.构建dom tree。(html中所有的标签都属于domtree里的元素)
2.遇到link或style,单独开启线程,异步加载样式,并构建cssom。
3.dom tree和cssom构建完毕后,形成render tree,然后开始渲染页面。
4.构建dom tree的过程中,遇到同步script则同步加载并执行script,script会参与dom tree的构建(如document.write不会覆盖页面) 。script执行结束后,继续往后构建dom tree。
5.构建dom tree的过程中,遇到图片、iframe资源会异步加载资源,不影响domtree、rendertree的构建及渲染。

现代浏览器,http请求回来页面后:
1.构建dom tree,并渲染已构建部分。
2.遇到link或style,单独开启线程,异步加载样式,并解析成cssom。cssom构建后,开始渲染已构建的domtree。
3.构建dom tree的过程中,遇到script则同步加载并执行script。script执行结束后,继续往后解析、渲染剩余部分。
4.遇到图片、iframe资源会异步加载资源,不影响render tree的渲染。但是css会影响其后面rendertree以及script的执行。

时间线

什么是时间线?
  • 从页面开始加载到页面全部加载完毕的这个过程,发生的每一件事的流程叫做时间线。
时间线
  1. 页面开始加载时,浏览器会先创建一个document对象,此时JS功能体就生效了(生成document对象就是JS行为)。
  2. 解析文档
  • 解析文档的定义:浏览器会把html文档从第一行阅读到最后一行
  • 解析文档的过程中会构建domtree
  1. 解析的过程中遇到link会异步加载css外部文件,构建domtree的同时,会根据style或css文件构建cssom。
  2. 如果遇到同步的script(一般默认都是同步的script,除非手动设置),会阻塞文档的解析,之前异步进行的cssom构建也会停止。直到script加载并执行完毕后,才会继续解析文档。
  3. 如果遇到异步的async script,异步加载js脚本并且执行,加载时不阻塞文档的解析。当加载结束后,会等当前正在运行的同步<script></script>执行结束后,开始执行。而不是等所有的同步<script></script>执行完后才执行
  • 使用async="async"、async="async"可以让脚本变异步(defer和async只能用其中的一个)。
  • 特殊:如果使用defer="defer"属性,异步脚本会等文档解析结束后,才运行
  • 异步脚本中无法使用document.write(),会静默失败。
  • 但如果在异步脚本的window.onload中使用document.write是可以重写整个文档。
  1. 遇到图片资源,首先会解析img这个节点,然后异步加载src里的图片资源,加载的过程不阻塞文档解析。
  2. 文档解析完成。
  3. 文档解析完成后,已加载完的defer script会按顺序开始执行。加载中的异步脚本(async和defer),不会阻塞defer脚本的执行。
  4. 文档解析完成后,会触发DOMContentLoaded事件,此时代表domtree构建完毕。但不代表所有的资源加载完成。
  • 此时程序由同步的脚本执行阶段进入事件驱动阶段。事件驱动阶段,代表用户可以和页面开始进行交互行为,如点击、输入等操作。
  1. 当异步脚本、css文件、图片等资源加载并执行结束后,最后会触发window的onload事件。(ajax请求属于js执行范畴,和时间线没有关系。ajax的回调运行在哪个环节,要看网络的快慢,有可能在onload之前,也可能在其之后。)

extends

  • 生命周期状态
    • document.readyState代表网页被执行的状态
    • 通过document.onreadystatechange可以监听生命周期状态的变化
    • 通过DOMContentLoaded可以监听domtree是否构建完毕
      • loading 代表domtree并render中;
      • interactive代表domtree构建完毕并进入可交互状态
      • complete代表页面全部加载完毕
<script type="text/javascript">
  console.log(document.readyState);  // loading
  document.onreadystatechange = function () { // 会被执行两遍
    console.log(document.readyState); 
    // domtree构建完为interactive;  
    // 页面全部加载完为complete;  
  }
  document.addEventListener('DOMContentLoaded', function () {
    console.log('loaded'); // 会和iteractive一起打印  他两代表同一个阶段
  })
</script>
  • window.onload和document.addEventListener('DOMContentLoaded')的区别

    • 前者要等所有资源全部加载完进行回调执行,后者当页面解析完(即domtree构建完)进行回调执行。
    • DOMContentLoaded等同于Jquery中的$(document).ready(function(){})、$(function(){})、$(document).on('ready', function(){})任意一种
    • DOMContentLoaded存在兼容性问题,以下为兼容代码


  • document.write

    • 以一个script为单位,同一script中的document.write会进行合并后一起渲染到页面。
    • 因此比较耗时的程序都会阻断当前脚本的docment.write。
    • 异步脚本中的document.write会静默失败。
    • alert会阻断所有脚本中的document.write,即使不在同一个script中,alert也会阻断之前script中的document.write。
  • alert

    • 会阻断页面的渲染
    • 阻断程序的执行
    • 阻断document.write

async script使用场景

  • 不会影响到其他模块的时候,可以使用async script。例如一些工具类,就不可以使用async。因为会被其他模块所依赖。但比如一些统计类的代码即可用到async script。

疑问

1.script文件,属于同步加载,为什么会在执行前面的代码时,后面的script文件就出现在了network里,但是没有开始下载?

  • 猜测:原因是浏览器首先会全部解析一遍文档,解析的过程中,会构建domtree、运行script。同时会继续解析后面的文档,寻找需要下载的资源,等待script运行结束后,开始下载。
  1. 图片资源加载时,是一遍下载一遍渲染?而不是等全部加载结束后才渲染。
    图片未给宽高,加载后是否会回流?
  • 测试后答案:一边下载一边渲染。不会造成回流,开始下载的那一刻就知道了宽高。
  1. css文件属于异步加载,加载结束后,会导致页面回流或重绘?
  • 如果是对已渲染的元素产生影响,有可能会回流或重绘。但对css后面的元素不会造成影响。因为后面的元素只是形成了domtree,还未生成rendertree。

相关文章

  • 16.1、时间线、解析与渲染、封装文档解析完毕函数

    浏览器渲染页面的过程 当网页被下载下来后,开始解析html文档,把需要用到的资源进行下载 当遇到script时,会...

  • DOM

    解析过程: HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树,getElementById是获...

  • 基础知识:浏览器的渲染

    渲染流程 渲染流程有四个主要步骤: 解析HTML生成DOM树: 渲染引擎首先解析HTML文档,生成DOM树 构建...

  • DOM概述

    1、解析过程HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树,getElementById是获...

  • 8.请简述虚拟dom的概念与实现原理

    在浏览器渲染网页的过程中,加载到HTML文档后,会将文档解析并构建DOM树,然后将其与解析CSS生成的CSSOM树...

  • DOM概述一

    类操作className 解析过程 HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树,getE...

  • 重绘和重排

    浏览器渲染引擎工作时,会先解析HTML然后生成DOM树,与此同时,渲染引擎也会用CSS解析器解析CSS文档构建CS...

  • 涨知识:浏览器的渲染机制

    浏览器渲染过程: 1、根据html文档解析构建DOM树 2、根据css文档解析构建CSSOM树 3、根据DOM和C...

  • 浏览器解析工作流程

    浏览器解析浏览器解析大概的工作流程大致可归纳为四个步骤: 解析HTML以构建DOM树:渲染引擎开始解析HTML文档...

  • JSX规则

    ReactDOM.render(标签\组件,容器,渲染后的回调函数) 解析规则 遇到<标签 用HTML 解析遇到 ...

网友评论

      本文标题:16.1、时间线、解析与渲染、封装文档解析完毕函数

      本文链接:https://www.haomeiwen.com/subject/hnimtktx.html