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 卸载前卸载:
<!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>
<!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()
消息描述的顺序触发。