DOMContentLoad事件在HTML解析完成、DOM树构建完毕时触发,不等待CSS、图片等外部资源加载,但会等待同步脚本执行完毕。

DOMContentLoad 事件触发时,HTML 解析到哪一步了
它发生在 Parse HTML 完成、但外部资源(如图片、字体、异步脚本)尚未加载完毕的时刻。此时 DOM 树已构建完成,所有同步 HTML 标签都被解析并生成节点,但 CSSOM 可能还没就绪,paint 也还没开始。
常见错误现象:在 DOMContentLoaded 回调里操作某个 class="sidebar" 元素,却拿不到 —— 很可能是因为该元素由后续 JS 动态插入,或 HTML 中实际写成了 class="siderbar" 拼错,而浏览器不会报错,只是查无此节点。
- JS 在
中同步引入会阻塞Parse HTML,直到Evaluate Script结束才继续解析后续标签 - CSS 文件如果出现在 JS 前面,且 JS 尝试读取样式(如
getComputedStyle),浏览器会等待 CSSOM 构建完成,间接导致 HTML 解析暂停 -
<script async></script>或<script defer></script>不会阻塞解析,但它们的执行时机不同:defer等 DOM 构建完再执行,async下载完就执行(可能早于 DOM 完成)
为什么 <link rel="stylesheet"> 会延迟 paint 却不总阻塞 parse
CSS 不阻塞 HTML 解析本身,但浏览器为安全起见,会暂停 paint 直到 CSSOM 构建完成 —— 因为渲染引擎需要知道每个元素最终计算出的样式才能绘制。你看到页面“白屏几秒”,大概率是卡在 Parse Stylesheet 阶段,而非 Parse HTML。
使用场景:首屏关键 CSS 应内联(<style></style>),非关键 CSS 用 media 属性或 loadCSS 方式异步加载,避免阻塞首次绘制。
立即学习“前端免费学习笔记(深入)”;
- 若 CSS 后紧跟同步
<script></script>,浏览器会等 CSSOM 就绪再执行脚本,此时Parse HTML实际被间接挂起 -
rel="preload"加载 CSS 不会触发解析,只预下载;必须配合onload手动插入<link>才真正参与 CSSOM 构建 - 滥用
@import会导致串行加载,比多个并行<link>更慢,尤其在嵌套层级深时
img 标签何时解码?是否影响 DOM 构建
<img alt="解析HTML页面渲染流程:浏览器是如何解析标签的" > 是典型的“不阻塞解析、不阻塞渲染(除首次解码)、不阻塞 DOM 构建”的标签。浏览器遇到 <img src="a.jpg" alt="解析HTML页面渲染流程:浏览器是如何解析标签的" > 会立即发起请求,但继续往下解析后续 HTML;图片解码和绘制则排队等 paint 阶段统一调度。
容易踩的坑:在 DOMContentLoaded 里通过 img.naturalWidth 读尺寸,结果是 0 —— 因为图片还没加载完成。应监听 img.onload 或用 decode() API 显式等待解码结束。
- 未设置
width/height的<img alt="解析HTML页面渲染流程:浏览器是如何解析标签的" >会导致回流(reflow),尤其在瀑布流布局中频繁触发 -
loading="lazy"仅对离屏图片延迟加载,不影响 DOM 解析顺序,但会推迟请求发起时间 - 服务端返回 404 的图片不会中断解析,但会在控制台报
Failed to load resource,且img.complete为false
Vue/React 模板编译中的 HTML 解析器行为差异
框架的模板编译阶段(如 Vue 的 parseHTML 函数、React 的 JSX 转换)并不运行在浏览器渲染流程中,而是构建时或首次挂载前的纯字符串处理。它们不触发 Parse HTML,也不生成真实 DOM 节点,只是产出 AST 或 VNode。
这意味着:你在 Vue SFC 里写的 <template><div v-if="flag">{{ msg }}</div></template>,其内部标签不会被浏览器原生解析 —— 它们被 parseHTML 当作普通字符串提取属性、指令、插值,再交由渲染函数处理。
- 框架解析器通常不校验 HTML 语法规范(比如允许自闭合
<my-comp></my-comp>),但浏览器原生解析器会自动补全缺失标签 - 服务端渲染(SSR)输出的 HTML 会被浏览器当作普通 HTML 再解析一次,所以 SSR 输出必须是合法 HTML,否则可能被重排(如
<table> 内直接放 <code><div>) <li>使用 <code>v-html或dangerouslySetInnerHTML注入的内容,才会真正进入浏览器的Parse HTML流程,此时 XSS 和标签嵌套风险完全交给浏览器处理
关键点在于:浏览器原生的 HTML 解析是单线程、顺序、容错的;而框架的“解析”是可控、可中断、面向抽象语法树的。两者共存但职责分离 —— 别指望
v-if 能跳过浏览器对某段 HTML 的解析,它根本没机会见到那段字符串。



















