Html 的生命周期
零、序言
vue 用多了,自然离不开生命周期。最近突发奇想,加上之前看过的文章中关于 script 标签中的 async 和 defer 的捣糨糊,决定整理一下,攻克这个模糊点。
当然,最多的还是与 script 标签相关的前两个周期,后俩个周期并没有过多的复杂点,因此会着重描述前两个。
参考文章:
1.页面生命周期
2.HTML,javascript,image等加载,DOM解析,js执行生命周期
一、页面周期
1.DOMContentLoaded - 浏览器已经加载了 Html, DOM 树已经构建完毕,但是 img 和外部样式表等资源可能还没有下载完毕。
2.load - 浏览器已经完全加载了所有资源。
3.beforeunload - 用户即将离开页面。
4.unload - 用户离开页面。
每一个事件都有特定的用途,前两个如其名,beforeunload 会给用户弹出个确认框,unload 则不会。
二、DOMContentLoaded
DOMContentLoaded 事件由 document 对象触发,我们可以使用 addEventListener 来触发。
正如前文所说,在这个事件触发的时候,我们如果获取某些 img 的宽度和高度的话,得到的可能是0。
当然这里是有陷阱的。
1. 与脚本(<script />)
首先有一点,浏览器的 UI 渲染线程和 JS 引擎是互斥的,当 JS 引擎执行时 UI 线程会被挂起。因此,当浏览器在解析 HTML 时遇到 <script /> 时,将不会继续构建 DOM 树,转而取解析、执行脚本,所以 DOMContentLoaded 有可能在所有脚本执行完毕之后触发。
外部脚本(通过 src 引入)的加载和解析和自带的一样会暂停 DOM 树的构建,这里 DOMContentLoaded 会等待。
不过有两个特殊的情况,如果外部脚本上带有 async 或者 defer 属性,那么浏览器会继续执行 DOM 解析而不需要等待脚本的完全执行,所以这一直时外部脚本的优化方案之一。(async 和 defer 属性仅对外部脚本起作用, 当 src 不存在的时候会被自动忽略)
关于 async 和 defer 与 DOM 的解析顺序如下图所示:
既然提到了 async 和 defer, 也顺带整理一下他们的异同:
async | defer | |
顺序 | 带有 async 的脚本是优先执行先加载完的脚本,即他们在页面中的顺序并不保证他们的执行顺序。 | 带有 defer 的脚本时按照他们在页面中出现的顺序依次执行。 |
DOMContentLoaded | 带有async 的脚本也许会在页面没有完全下载完之前就加载,这种情况会在脚本很小或本缓存,并且页面很大的情况下发生。 |
带有defer 的脚本会在页面加载和解析完毕后执行,刚好在 DOMContentLoaded 之前执行。 |
所以 async 用在完全没有依赖和被依赖的脚本上。
三、load
load 事件是在 window 对象上的,这与 DOMContentLoaded 不同。该事件在所有文件包括样式表,图片和其他资源下载完毕后触发。既然这样规定,自然该干啥干啥,没什么明显的陷阱。
四、beforeunload
如果用户即将离开页面或关闭窗口时,beforeunload 事件将会被触发以进行额外的确认。举个例子:
1 2 3 | window.onbeforeunload = function () { return "There are unsaved changes. Leave now?" ; }; |
当然,如果在 chrome 和 firefox 浏览器中会忽略返回的自定义的字符串,这是出于安全考虑的。
五、unload
unload 事件与 load 事件一样,是在 window 对象上的,触发时间为用户关闭该页面的时候,我们可以做一些不存在延时的任务,比如关闭弹层等等。
六、readyState
document.readyState 这个只读属性可以告诉程序当前文档加载到哪一个步骤,它有三个值:
1. loading - 加载,document 仍在加载中;
2. interactive - 互动,文档已经完成加载,文档已被解析,但是诸如图像,样式表和框架之类的子资源仍在加载。
3. complete - 文档和所有子资源已完成加载。状态表示 load
事件即将被触发。
而这个属性的每次改变同样有一个事件可以监听:
1 | document.addEventListener( 'readystatechange' , () => console.log(document.readyState)); |
不过这个 change 事件很少会被用到,可能出现的地方在某些第三方类库中判断一些依赖关系等地方。不详述,具体可移步文首的文章或者 MDN。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战