Skip to main content

HTML 页面生命周期 API

HTML 页面的生命周期事件包括:

  • document - DOMContentLoaded:浏览器已加载完 DOM,但图片和样式表等外部资源可能尚未加载完成;
  • window - load:浏览器不仅加载完 DOM,还完成了所有图片、样式等外部资源的加载;
  • document - readystatechange:文档的加载状态变化时会触发 readystatechange
  • window - beforeunload:当浏览器窗口关闭或刷新时触发,可以检查用户是否保存了更改,并询问是否真的要离开;
  • window - unload:用户已经离开,但仍可以启动一些操作,例如发送统计数据。

一、DOMContentLoaded

DOMContentLoaded 事件发生在 document 对象上,必须使用 addEventListener 来捕获:

document.addEventListener("DOMContentLoaded", ready);

示例:

<script>
function ready() {
// 图片目前尚未加载完成(除非已经被缓存),所以图片的大小为 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">

上面 DOMContentLoaded 在文档加载完成后触发,虽然可以查看 <img> 元素,但不会等待图片加载,因此 alert 显示图片大小为零。

浏览器内建的自动填充

Firefox、Chrome 和 Opera 都会在 DOMContentLoaded 中自动填充表单。

如果 DOMContentLoaded 被需要加载很长时间的脚本延迟触发,那么自动填充也会等待。所以在某些网站上可能会看到登录名/密码字段不会立即自动填充的情况,这是 DOMContentLoaded 事件之前的延迟。

二、load

当页面所有资源加载完成时,会触发 window 对象上的 load 事件。

下面的这个示例正确显示了图片大小,因为 window.onload 会等待所有图片加载完毕:

<script>
window.onload = function() { // 也可以用 window.addEventListener('load', (event) => {
// 此时图片已经加载完成
alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
};
</script>

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

三、readystatechange

document.readyState 表示文档的加载状态,包括:

  • loading:正在加载;
  • interactive:文档结束加载并且被解析,但图片、样式和 frame 等子资源仍在加载;
  • complete:文档和所有子资源已完成加载。

加载状态 readyState 的改变会触发 document 的 readystatechange 事件。

// 当前状态
console.log(document.readyState);

// 状态改变时打印它
document.addEventListener('readystatechange', () => console.log(document.readyState));

readystatechange 事件是跟踪文档加载状态的另一种机制,它很早就存在,但现在则很少被使用。

四、beforeunload

如果访问者触发了离开页面的导航(navigation)或试图关闭窗口,beforeunload 处理程序将要求进行更多确认。

beforeunload 事件中调用 window.alert()window.confirm() 以及 window.prompt() 方法可能会失效,如果要触发一个确认对话框,询问用户是否真的要离开该页面,可以通过以下方式:

window.addEventListener('beforeunload', (event) => {
// Cancel the event as stated by the standard.
event.preventDefault();
// Chrome requires returnValue to be set.
event.returnValue = '';
});

五、unload

当用户离开页面时,window 对象上的 unload 事件就会被触发,可以在这里做一些不涉及延迟的操作,例如关闭相关的弹出窗口。

注意 unload 事件也遵循文档树:父 iframe 会在子 iframe 卸载前卸载:

Parent Frame
<!DOCTYPE html>
<html>
<head>
<title>Parent Frame</title>
<script>
window.addEventListener('beforeunload', function(event) {
console.log('I am the 1st one.');
});
window.addEventListener('unload', function(event) {
console.log('I am the 3rd one.');
});
</script>
</head>
<body>
<iframe src="child-frame.html"></iframe>
</body>
</html>
Child Frame
<!DOCTYPE html>
<html>
<head>
<title>Child Frame</title>
<script>
window.addEventListener('beforeunload', function(event) {
console.log('I am the 2nd one.');
});
window.addEventListener('unload', function(event) {
console.log('I am the 4th and last one…');
});
</script>
</head>
<body>

</body>
</html>

当父 iframe 被卸载,事件将按 console.log() 消息描述的顺序触发。