页面生命周期

258 阅读3分钟

HTML页面的生命周期有以下三个重要事件:

  • DOMContentLoaded:浏览器已经完全加载了HTMLDOM树已经构建完毕,但是像是img和样式表等外部资源可能并没有下载完毕

  • load:浏览器已经加载了所有的资源(图像,样式表等)

  • beforeunload/unload:当用户离开页面的时候触发

来看一下每个事件的细节:

1.DOMContentLoaded

(1)DOMContentLoadeddocument对象触发

我们使用addEventListener来监听它:

document.addEventListener('DOMContentLoaded', ready);

举个栗子

<script>
  function ready() {
    alert('DOM is ready');

    // image is not yet loaded (unless was cached), so the size is 0x0
    alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
  }

  document.addEventListener('DOMContentLoaded', ready);
</script>

<img id="img" src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">

在这个例子中DOMContentLoadeddocument加载完成后就被触发,无需等待其他资源的载入,所以alert输出的图像的大小为0。这么看来DOMContentLoaded似乎很简单,DOM树构建完毕之后就运行该事件,不过其实存在一些陷阱。

(2)DOMContentLoaded和脚本

当浏览器在解析HTML页面时遇到了 <script>...</script> 标签,将无法继续构建DOM树(UI渲染线程与JS引擎是互斥的,当JS引擎执行时UI线程会被挂起),必须立即执行脚本。所以DOMContentLoaded有可能在所有脚本执行完毕后触发。

外部脚本(带src的)的加载和解析执行也会暂停DOM树构建,所以DOMContentLoaded也会等待外部脚本。

不过有两个例外是带asyncdefer的外部脚本,asyncdefer属性仅仅对外部脚本起作用,并且他们在src不存在时会被自动忽略。

他们有两处不同:

  • 顺序:带有async的脚本是优先执行先加载完的脚本,他们在页面中的顺序并不影响他们执行的顺序。带有defer的脚本按照他们在页面中出现的顺序依次执行。
  • DOMContentLoaded:带有async的脚本也许会在页面没有完全下载完之前就加载,这种情况会在脚本很小或本地缓存,并且页面很大的情况下发生。带有defer的脚本会在页面加载和解析完毕后执行,刚好在DOMContentLoaded之前执行。

(3)浏览器的自动补全

Firefox, ChromeOpera会在DOMContentLoaded执行时自动补全表单。

例如,如果页面有登录的界面,浏览器记住了该页面的用户名和密码,那么在DOMContentLoaded运行的时候浏览器会试图自动补全表单(如果用户设置允许)。

所以如果DOMContentLoaded被一个需要长时间执行的脚本阻塞,那么自动补全也会等待。你也许见过某些网站(如果你的浏览器开启了自动补全)—— 浏览器并不会立刻补全登录项,而是等到整个页面加载完毕后才填充。这就是因为在等待DOMContentLoaded事件。

使用带asyncdefer的脚本的一个好处就是,他们不会阻塞DOMContentLoaded和浏览器自动补全。(译注:其实执行还是会阻塞的)

2.window.onload

window对象上的onload事件在所有文件包括样式表,图片和其他资源下载完毕后触发。下面的例子正确检测了图片的大小,因为window.onload会等待所有图片的加载。

<script>
  window.onload = function() {
    alert('Page loaded');

    // image is loaded at this time
    alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
  };
</script>

<img id="img" src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">

3.window.onbeforeunload

如果用户即将离开页面或者关闭窗口时,beforeunload事件将会被触发以进行额外的确认。浏览器将显示返回的字符串,举个例子:

window.onbeforeunload = function() {
  return 'There are unsaved changes, Leave now?';
};

4.document.readyState

参考:www.jianshu.com/p/3b581af02…