原来 HTML 也有生命周期

说起“生命周期”,你可能第一反应是 Vue、React 这样的前端框架。但你有没有想过:HTML 页面,其实也有自己的生命周期!

虽然 HTML 本身没有框架那样的生命周期钩子,但浏览器在加载、解析、渲染、交互、关闭整个页面过程中,其实经历了一整套完整的流程,而且我们可以通过一些原生事件精确监听这些“节点”。

今天就来拆解一下:HTML 的生命周期,到底是怎么回事?


1. HTML 的“出生”:从请求到解析

当用户在地址栏输入一个 URL 或点击一个链接,浏览器会向服务器发送 HTTP 请求。服务器返回 HTML 文件后,浏览器开始执行  从头到尾的读取和解析

这个阶段包含:

  • DNS 解析
  • TCP 连接
  • 发送请求
  • 接收 HTML 响应
  • 开始解析 HTML

生命周期阶段名词对应:

HTML载入开始 ≈ HTML生命周期的诞生

2. 解析+构建阶段:DOM 树和 CSSOM 树的建立

HTML 不是直接显示在页面上的,它会被浏览器解析成一个结构化的  DOM 树(文档对象模型),这个过程叫做“构建 DOM”。

  • HTML 标签被逐个读取
  • 标签转换为 DOM 节点
  • 遇到 <script> 标签可能会阻塞解析(除非加了 deferasync

与此同时,CSS 也被解析并构建成 CSSOM 树。

等到 DOM 和 CSSOM 都准备好后,合成一棵叫 Render Tree  的渲染树,准备开始绘制。

生命周期事件:DOMContentLoaded

document.addEventListener("DOMContentLoaded", function () {
  console.log("DOM 已构建完成(不等样式图像)");
});

这个事件表示:HTML 已经完全解析完毕,DOM 树构建完成,但此时图片、样式表等静态资源可能还没加载完


3. 页面渲染阶段:可视化生命周期

这时页面进入了“可视化”生命周期:

  • 布局(Layout):计算每个元素的位置和尺寸
  • 绘制(Paint):把每个节点变成像素
  • 合成(Composite):最终绘制到屏幕上

这一阶段就像 HTML 的“成长”阶段:从代码变成真实可见的页面。

生命周期事件:window.onload

window.onload = function () {
  console.log("页面所有资源加载完毕(包括图片、样式等)");
};

这个事件意味着:整个页面,包括所有静态资源都已加载完成。


4. 交互阶段:事件绑定、脚本执行

当页面渲染完毕,用户开始滚动、点击、输入,这时页面进入了一个相对“稳定但活跃”的阶段。

JS 脚本也在这个时候开始大量运行,比如:

  • 加载动态数据(AJAX)
  • 动画/滚动监听
  • 表单校验
  • 用户交互反馈

这个阶段,就是 HTML 生命周期中的“成熟期”。


5. 页面卸载:生命周期的终结

当用户关闭标签页、刷新页面或跳转到其他链接,页面就会被卸载。

生命周期事件: beforeunload  和 unload

window.addEventListener("beforeunload", function (e) {
  e.preventDefault(); // 有些浏览器需要显式调用
  e.returnValue = "确定离开吗?"; // 显示提示(部分浏览器支持)
});
  • beforeunload:页面即将离开时触发,可用来做离开确认、保存状态。
  • unload:页面已经要离开,不能再交互,适合做一些清理动作。
window.addEventListener("unload", function () {
  console.log("页面即将卸载,可做清理工作");
});

小结

阶段 描述 可用事件
加载开始 开始解析 HTML 文件
DOM 构建 DOM 树生成完成 DOMContentLoaded
渲染完成 所有资源加载完毕,页面可见 load (即 window.onload
交互中 脚本运行、用户交互 所有 JS 事件监听
即将卸载 离开当前页面 beforeunload
卸载完成 页面销毁,释放内存 unload

  • 使用 DOMContentLoaded  来初始化依赖 DOM 的脚本(如:绑定按钮事件)
  • 使用 window.onload  来初始化依赖图片或其他资源的逻辑
  • 避免在 unload  做太多事情,现代浏览器可能不会等你处理完
  • 不推荐频繁使用 beforeunload 弹窗提示,用户体验较差