当前位置: 首页 > Web前端 > HTML

页面生命周期:DOMContentLoaded,load,beforeunload,unload

时间:2023-04-02 13:43:07 HTML

页面生命周期:DOMContentLoaded,load,beforeunload,unload原文地址:http://javascript.info/onload...一个HTML页面的生命周期有以下三种importantEvent:DOMContentLoaded——浏览器已经完全加载了HTML,DOM树已经构建完成,但是和样式表等外部资源可能还没有下载。加载——浏览器已经加载了所有资源(图像、样式表等)。beforeunload/unload——当用户离开页面时触发。每个事件都有一个特定的目的DOMContentLoaded——DOM已加载,因此js可以访问所有DOM节点并初始化界面。load--附加资源已经加载,你可以在这个事件触发时获取图像的大小(如果没有在HTML/CSS中指定)beforeunload/unload--用户正在离开页面:你可以询问用户是否他们保存更改,如果他们确定离开页面。查看每个事件的详细信息。DOMContentLoadedDOMContentLoaded由文档对象触发。我们使用addEventListener来监听它:document.addEventListener("DOMContentLoaded",ready);例如在这个例子,DOMContentLoaded是在文档加载完成后触发的,不需要等待其他资源加载完毕,所以alert输出的图片大小为0。从这个角度来看,DOMContentLoaded似乎很简单,事件就是在DOM树构建完成后运行,但实际上有一些陷阱。DOMContentLoaded和script当浏览器在解析HTML页面时遇到标签,将无法继续构建DOM树(译注:UI渲染线程和JS引擎是互斥的,当JS引擎执行UI线程时会被挂起),脚本必须立即执行。所以DOMContentLoaded可能会在所有脚本执行完毕后触发。加载和解析外部脚本(带src)也会暂停DOM树的构建,所以DOMContentLoaded也会等待外部脚本。但是,有两个例外是带有异步和延迟的外部脚本。它们告诉浏览器继续解析而不等待脚本执行,这样用户就可以在脚本加载之前看到页面,这样有更好的用户体验。async和defer属性只对外部脚本有效,当src不存在时会被自动忽略。它们都告诉浏览器在后台加载脚本的同时继续处理页面上的内容,等脚本加载完成后再执行。所以脚本不会阻塞DOM树的构建和页面的渲染。(译注:其实这是不对的,带async和defer的脚本下载与HTML的下载解析是异步的,但是js的执行必须和UI线程互斥,如下图,下载完成后执行async会阻塞HTML的解析)它们有两个区别:asyncdefer顺序脚本和async是最先加载的脚本,它们在页面上的顺序不影响它们的执行顺序。带有defer的脚本按照它们在页面上出现的顺序执行。具有异步功能的DOMContentLoaded脚本可能会在页面完全下载之前加载。当脚本很小或被缓存,而页面很大时,就会发生这种情况。带有defer的脚本在页面加载和解析之后执行,就在DOMContentLoaded之前。所以async用于完全不依赖于其他脚本的脚本。###DOMContentLoaded和stylesExternal样式表不会影响DOM,因此`DOMContentLoaded`不会等待它们。但是有一个陷阱:如果我们在样式之后有一个脚本,那么该脚本必须等待样式表执行:发生这种情况的原因是脚本可能会像上面的示例一样获取一些元素坐标或基于样式的属性。所以他们自然要等到样式加载完毕后才能执行。DOMContentLoaded需要等待脚本的执行,脚本需要等待样式的加载。浏览器自动完成Firefox、Chrome和Opera将在执行DOMContentLoaded时自动完成表单。例如,如果页面有一个登录屏幕并且浏览器记住了该页面的用户名和密码,那么当DOMContentLoaded运行时浏览器将尝试自动完成表单(如果用户设置允许)。因此,如果DOMContentLoaded被需要很长时间执行的脚本阻塞,自动完成也会等待。您可能已经看到一些网站(如果您的浏览器打开了自动完成)——浏览器不会立即完成登录,而是等到整个页面加载完毕。这是因为等待DOMContentLoaded事件。使用带有async和defer的脚本的好处之一是它们不会阻止DOMContentLoaded和浏览器自动完成。(译注:其实执行还是会阻塞)window.onloadwindow对象上的onload事件在包括样式表、图片等资源在内的所有文件下载完成后触发。下面的示例正确检测了图像的大小,因为window.onload将等待所有图像加载。window.onunload当用户离开页面时,window对象unload事件会被触发,我们可以不加延迟地做一些事情,比如关闭弹窗,但是我们不能阻止用户转移到另一个页面。所以我们需要使用另一个事件——onbeforeunload。window.onbeforeunload如果用户即将离开页面或关闭窗口,会触发beforeunload事件进行额外确认。浏览器会显示返回的字符串,例如:window.onbeforeunload=function(){return"Thereareunsavedchanges.Leavenow?";};某些浏览器如Chrome和Firefox会忽略返回的字符串,而是显示浏览器自己的文本,这是出于安全考虑,以确保用户不被错误消息误导。readyState如果我们在整个页面加载后设置DOMContentLoaded会发生什么?没什么,不会触发DOMContentLoaded。在某些情况下,我们无法确定页面是否已加载。比如用async加载和执行一个外部脚本就是异步的(注意:执行不是异步的-_-)。在不同的网络条件下,脚本可能在页面加载之后执行,也可能在页面加载之前执行,我们无法确定。所以我们需要知道页面加载的状态。document.readyState属性为我们提供加载信息并具有三个可能的值:loading-文档仍在加载中。interactive-文档已完成加载,文档已被解析,但图像、样式表和框架等子资源仍在加载中。complete-文档和所有子资源已完成加载。该状态表示即将触发加载事件。所以我们可以查看document.readyState的状态,如果没有就绪,我们可以选择挂载事件,如果就绪,我们可以直接立即执行。像这样:functionwork(){/*...*/}if(document.readyState=='loading'){document.addEventListener('DOMContentLoaded',work);}else{work();}每当文档每当加载状态发生变化时都会触发readystatechange事件,因此我们可以打印所有状态。//当前状态console.log(document.readyState);//打印状态变化document.addEventListener('readystatechange',()=>console.log(document.readyState));readystatechange是一种可选的跟踪页面加载的方式,很久以前就有了。不过现在已经很少用了,为了完整起见还是先介绍一下吧。每个事件中readystatechange的执行顺序是怎样的?输出如下:[1]initialreadyState:loading[2]readyState:interactive[2]DOMContentLoaded[3]iframeonload[4]readyState:complete[4]imgonload[4]windowonload方括号中的数字代表它们加载的时间发生。实际发生的时间会稍晚一些,但是同号的时间可以认为是同时顺序触发的(错误在几毫秒内)document.readyState在DOMContentLoaded之前就变成交互的了,这两个事件可以被认为是同时发生的。document.readyState在所有资源(包括iframe和img)加载完毕后变为complete,我们可以看到complete,img.onload和window.onload几乎是同时发生的,不同的是window.onload是在所有其他加载事件之后执行的。总结一下页面事件的生命周期:DOMContentLoaded事件在DOM树构建完成后触发,这个阶段我们可以使用js访问元素。async和defer的脚本可能还没有执行。图像和其他资源文件可能仍在下载。加载页面上的所有资源后触发加载事件。通常我们不使用这个事件,因为我们不需要等待那么久。beforeunload在用户即将离开页面时触发,它返回一个字符串,浏览器将显示给用户并询问这个字符串以确定是否离开。unload在用户离开时触发。这个阶段我们只能做一些不能拖延的操作。由于各种限制,很少使用。document.readyState表示页面的加载状态,可以在readystatechange中跟踪:loading—页面正在加载。交互式——页面被解析,它与DOMContentLoaded同时发生,但顺序在它之前。complete——页面上所有的资源都已经加载完毕,时间上和window.onload同时发生,但是顺序在他之前。