Simonzhangs' blog Simonzhangs' blog
首页
  • 前端文章

    • HTML
    • CSS
    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • JS设计模式总结
  • 《Vue》
  • 《React》
  • 《TypeScript 从零实现 axios》
  • TypeScript
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • apple music
  • extension
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Simonzhangs

前端学习探索者
首页
  • 前端文章

    • HTML
    • CSS
    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • JS设计模式总结
  • 《Vue》
  • 《React》
  • 《TypeScript 从零实现 axios》
  • TypeScript
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • apple music
  • extension
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 技术文档

  • GitHub技巧

  • Nodejs

  • 博客搭建

  • Ajax

  • 计算机网络

  • 计算机编译原理

  • 涨知识

    • JavaScript的字符编码
    • 包装对象
    • Web页面的生命周期
      • 一、前言
      • 二、Web 页面生命周期演示
      • 三、Web 页面生命周期总结
      • 四、async、defer 与 DOMContentLoaded 顺序
        • 1. 带async的script
        • 2. 带defer的script
  • 技术
  • 涨知识
simonzhangs
2022-05-19
目录

Web页面的生命周期

我们经常提到 Vue 的生命周期,在合适的生命周期做 DOM 操作是很重要的。除了了解框架的生命周期,原生 Web 页面的生命周期也是必须掌握的,比如最常遇到的 DOMContentLoaded、load,当然还有 beforeunload、unload 等等。

# 一、前言

理解 WEB 页面的生命周期,文档加载事件及顺序对 WEB 开发有十分的重要意义。如果不理解,在元素未加载就提前操作元素,则得不到想要的结果;而如果页面完全加载完成后,再进行操作,则又会影响用户体验。

一般来说,大多数的操作我们都应该放在 DOMContentLoaded 事件中执行。采用如下形式:

document.addEventListener("DOMContentLoaded", function () {
  alert("DOMContentLoaded");
});
1
2
3

当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。

# 二、Web 页面生命周期演示

理解 WEB 页面的生命周期,文档加载事件及顺序对 WEB 开发有十分的重要意义。比如说在 JQuery 中,我们大多将代码写在$(document).ready()中,当文档加载完成后,就会执行该函数。如果不这样做,在文档未加载完成之前操作 DOM,就得不到想要的结果;在 Vue 中,我们对于 DOM 的操作大多放在 mounted(){}生命周期中,此时虚拟 DOM 已经渲染到真实页面上了。

演示程序如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>
      HTML页面的生命周期,DOMContentLoaded、load、beforeunload、unload
    </title>
  </head>
  <body>
    <div id="main"></div>
    <iframe
      src="http://res.42du.cn/static/html/iframe.html"
      height="35"
      onload="append('iframe onload')"
    ></iframe>
    <div>
      <img
        src="http://res.42du.cn/up/201802/cbbtiga6.jpg?cache=none"
        onload="append('image onload')"
      />
    </div>
    <script>
      var output = "";
      function print() {
        document.getElementById("main").innerHTML += output;
      }
      function append(data) {
        output += data + " <br />";
      }
      document.addEventListener("readystatechange", function () {
        append("readyState : " + document.readyState);
      });
      document.addEventListener("DOMContentLoaded", function () {
        append("DOMContentLoaded");
      });
      window.onload = function () {
        append("window onload");
        print();
      };
      append("script executed");
    </script>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

从演示程序运行结果,得出一般浏览器的加载顺序如下:

  • script executed
  • readyState : interactive
  • DOMContentLoaded
  • image onload
  • iframe onload
  • readyState : complete
  • window onload

从以上可以看出痛的 script 总是先于其它事件执行,而 window.onload 事件总是最后执行;而 imgae onload 和 iframe onload 的先后顺序并不确定。

# 三、Web 页面生命周期总结

关于 WEB 页面的生命周期,有以下特点:

  • 同步的 JavaScript 脚本最先执行,它先于 DOMContentLoaded 事件执行;
  • 当 DOM 准备就绪时,DOMContentLoaded 事件在 document 上触发,可以在这个阶段利用 JavaScript 来操作 DOM 元素;
    • 所有脚本都执行完毕,除了那些外部使用异步(async)或延迟(defer)加载的脚本;
    • 图片和其他资源可能仍在载入过程中。
  • window 的 onload 事件,在页面加载所有资源后触发;一般很少使用它,因为通常的操作不用等到最后才执行。
  • window 的 beforeunload 事件,该事件在用户准备离开页面,在 unload 事件之前触发。如果 beforeunload 返回一个字符串,浏览器会给出用户是否真的想离开的提示。
  • window 的 unload 事件,当用户最终离开时会触发该事件。在 unload 的事件处理程序中,只能做简单的事情,不涉及延迟或询问用户。由于这个限制,它很少使用。
  • document.readyState 表示文档的当前状态,可以在 readystatechange 事件中跟踪文档状态的变更:
    • loading:文档正在载入
    • interactive:document 已经解析完毕时触发,几乎与 DOMContentLoaded 同时发生,但在 DOMContentLoaded 事件之前触发;
    • complete:文档和资源加载完成时触发,几乎与 window.onload 同时发生,但在 onload 事件之前触发。

一般来说,大多数的操作我们都应该放在 DOMContentLoaded 事件中执行,而不要放在 window.onload 中执行。

# 四、async、defer 与 DOMContentLoaded 顺序

除了同步的JS脚本外,还有异步的脚本,可以通过声明async或defer属性来异步加载脚本。

# 1. 带async的script

async脚本的加载不计入DOMContentLoaded事件统计,也就是说下图两种情况都是有可能发生的:

  • HTML 还没有被解析完的时候,async脚本已经加载完了,那么 HTML 停止解析,去执行脚本,脚本执行完毕后触发DOMContentLoaded事件;

带async的script-1 (opens new window)

  • HTML 解析完了之后,async脚本才加载完,然后再执行脚本,那么在HTML解析完毕、async脚本还没加载完的时候就触发DOMContentLoaded事件。

带async的script-2 (opens new window)

# 2. 带defer的script

文档解析时,遇到设置了defer的脚本,就会在后台进行下载,但是并不会阻止文档的渲染,当页面解析和渲染完毕后,会等到所有的defer脚本加载完毕并按照顺序执行完毕才会触发DOMContentLoaded事件,也就是说下图两种情况都是有可能发生的:

  • HTML 还没有被解析完的时候,defer脚本已经加载完了,那么 等待HTML 解析完成后执行脚本,脚本执行完毕后触发DOMContentLoaded事件。

带defer的script-1

  • HTML 解析完了之后,defer脚本才加载完,然后再执行脚本,脚本执行完毕后触发DOMContentLoaded事件。

带defer的script-2


参考文章:

图解<script>的 defer / async 与 DOMContentLoaded / Load (opens new window)

WEB 页面的生命周期,DOMContentLoaded,load,beforeunload,unload (opens new window)

编辑 (opens new window)
上次更新: 2022/06/16, 10:52:37
包装对象

← 包装对象

最近更新
01
一些有意思的类比
06-16
02
the-super-tiny-compiler解析
06-06
03
计算机编译原理总概
06-06
更多文章>
Theme by Vdoing | Copyright © 2021-2022
蜀ICP备2021023197号-2
Simonzhans | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
  • 飙升榜
  • 新歌榜
  • 云音乐民谣榜
  • 美国Billboard榜
  • UK排行榜周榜