- 教程
【免费下载链接】jstips
This is about useful JS tips!
在网页开发中,经常需要等 DOM 或整份文档加载完成后再执行初始化逻辑。本指南以 jstips 仓库的第 46 号技巧(繁體中文原文,另有 英文版、简体中文版、西班牙语版)为骨架,系统讲解如何在不依赖任何框架的前提下,跨浏览器地检测文档加载状态。读完本文,你将掌握document.readyState的三种取值、三种纯 JavaScript 检测方案及其适用场景,并能在实际项目中写出稳定可靠的加载检测逻辑。
核心概念:document.readyState 的三种状态
document.readyState是文档对象(document)提供的一个只读字符串属性,用来描述文档当前的加载进度。它是跨浏览器检测加载状态的基石,这也是本技巧强调"cross-browser(跨浏览器)"的原因——该属性在现代浏览器中均有稳定实现。
readyState只会取以下三个值之一:
| 取值 | 含义 | 触发时机 |
|---|---|---|
loading | 文档仍在加载中 | 浏览器开始解析 HTML 文档时 |
interactive | 文档已完成解析,DOM 可访问,但图片、样式表、iframe 等子资源仍在加载 | DOM 解析完成、DOMContentLoaded事件即将触发时 |
complete | 文档及其所有子资源(图片、样式表等)都已加载完成 | load事件触发时 |
理解这三个状态之间的递进关系,是正确使用本技巧的前提:loading → interactive → complete,状态只会单向推进,不会回退。
方式一:立即检查当前是否已加载完成
如果脚本本身是在文档加载之后才被引入或执行的(例如放在页面底部的<script>,或由异步方式加载),此时文档可能已经处于complete状态。可以直接做一次即时判断:
if (document.readyState === 'complete') { // 網頁已經完全載入 }这段代码正是原文档给出的第一段示例。它的适用场景是:你的初始化函数可能在文档加载前、加载中、加载后任意时刻被调用,因此需要先做一次即时检查,避免在文档尚未就绪时操作 DOM 而报错。
方式二:setInterval 轮询等待加载完成
如果脚本在文档加载早期(如<head>中)就被执行,此时readyState还是loading,直接判断会得到false。原文档给出的轮询方案如下:
let stateCheck = setInterval(() => { if (document.readyState === 'complete') { clearInterval(stateCheck); // 文件載入 } }, 100);实现要点:
- 间隔 100ms:原文档固定使用 100 毫秒作为轮询周期,在及时性与性能开销之间取得了平衡;
- 自清理机制:一旦检测到
complete状态,立即调用clearInterval(stateCheck)停止轮询,避免定时器永久空转消耗资源。这是本方案的关键细节——忘记清理定时器是常见的资源泄漏来源; - 闭包引用:定时器句柄
stateCheck被clearInterval引用,必须在检测成功的分支内清理。
方式三:onreadystatechange 事件监听
轮询之外,文档还提供了事件驱动方案——readystatechange事件。每当readyState发生变化时,该事件都会触发一次,因此无需主动轮询:
document.onreadystatechange = () => { if (document.readyState === 'complete') { // 文件載入 } };该方案的优劣:
- 优点:事件驱动、无固定间隔的轮询开销,状态变化时立即得到通知;
- 注意点:
onreadystatechange会在readyState每次变化时都触发(即loading → interactive、interactive → complete各触发一次),所以回调内必须用if过滤出目标状态,避免重复执行; - 局限:
onreadystatechange是document上的on*属性式事件处理器,同一时刻只能挂一个处理器,后者会覆盖前者。若需挂载多个监听器,可改用document.addEventListener('readystatechange', handler)(此用法与原文档同系列技巧 DOM event listening made easy 中强调的"使用具名引用以便移除"的最佳实践一致)。
区分"DOM 已就绪"与"页面完全加载"
原文档最后特别指出:使用document.readyState === 'interactive'可以检测 DOM 是否已加载完成。这一区分在实际开发中非常重要:
interactive(DOM 就绪):HTML 已解析完毕、DOM 树可安全访问,适合做事件绑定、DOM 查询、初始化渲染等不依赖图片尺寸的操作;complete(完全加载):所有子资源(图片、样式、iframe、脚本)都加载完毕,适合做需要依赖图片尺寸、资源度量、统计上报等操作。
一个常见的实战场景是:页面骨架渲染和事件绑定应尽早执行(等interactive即可),而依赖完整资源加载的分析类逻辑则需等到complete。
与其他加载检测方案的横向对比
为了写出贴合实战的代码,有必要将readyState方案与常见的加载检测手段放在一起对比:
| 方案 | 触发时机 | 特点 |
|---|---|---|
document.readyState === 'interactive' | DOM 解析完成 | 纯属性判断,可在任意时刻检测,无事件订阅成本 |
DOMContentLoaded事件 | DOM 解析完成 | 只能"订阅未来事件",若文档已加载完成则不再触发 |
document.readyState === 'complete' | 全部子资源加载完成 | 纯属性判断,语义明确 |
window.onload事件 | 全部子资源加载完成 | 与complete大致同步,但同为on*属性式处理器 |
jQuery$(document).ready() | DOM 解析完成 | 需要引入 jQuery 库 |
readyState方案的独特优势在于:它是属性而非事件,可以"事后检查"。事件方案只能面向未来,而属性判断无论脚本在任何时刻执行都能得到准确答案。这也是原文档反复强调"使用 pure JavaScript(纯 JavaScript)"的用意——不依赖 jQuery 或其他库,即可获得与框架等价的加载检测能力。jstips 仓库中另有多篇纯原生实现的技巧可与此互补,例如 Observe DOM changes in extensions 展示了用MutationObserver监听动态 DOM 变化,二者结合可以在文档就绪后继续追踪后续的 DOM 变更。
实战封装:一个可复用的 ready 检测工具
综合原文档的三种方案,可以封装一个兼顾"即时判断"与"事后订阅"的通用工具函数:
// 当 DOM 就绪时执行 callback(兼容"已就绪"与"尚未就绪"两种场景) function onDomReady(callback) { // 情况一:文档已解析完成(interactive 或 complete),立即执行 if (document.readyState === 'interactive' || document.readyState === 'complete') { callback(); return; } // 情况二:文档仍处于 loading,订阅 DOMContentLoaded 事件 document.addEventListener('DOMContentLoaded', callback); }若初始化逻辑强依赖图片等子资源,可将判断条件改为document.readyState === 'complete',或订阅window的load事件。若要兼容非常老旧的浏览器(不支持DOMContentLoaded),则可以退回到原文档的setInterval轮询方案,将callback()放入检测到complete的分支内并clearInterval清理定时器。
兼容性与注意事项小结
- 跨浏览器:
readyState与readystatechange在现代浏览器中支持良好,这正是本技巧称其"跨浏览器"的依据; - 事件与属性不可互相替代:事件方案"面向未来",属性方案"面向当下",实战中应像上文封装示例那样两者结合;
- 务必清理定时器:使用
setInterval方案时,在检测成功分支内clearInterval必不可少,否则会造成不必要的资源占用; - 区分两种就绪语义:
interactive只保证 DOM 可用,complete才保证所有子资源可用,请按实际业务需求选择。
本文内容对应 jstips 仓库第 46 号技巧,完整 tip 列表可参见 README.md,其中记录了该技巧在 en 语言分类下的条目。将该技巧与仓库内其他原生 DOM 相关技巧(如事件监听、DOM 变化观察)配合阅读,可以构建一套完全不依赖框架的前端初始化与 DOM 操作体系。
- 教程
【免费下载链接】jstips
This is about useful JS tips!
相关推荐
jstips 46:用纯 JavaScript 检测 document ready——readyState 三种姿势完整实战
jstips 46:用纯 JavaScript 检测 document ready——readyState 三种姿势完整实战 在 Web 开发中,"页面(DOM
教程jstips 第 46 期:纯 JavaScript 检测 document ready——基于 readyState 的跨浏览器监听方案
jstips 第 46 期:纯 JavaScript 检测 document ready——基于 readyState 的跨浏览器监听方案 本篇基于 jstip
教程Officegen终极指南:使用纯JavaScript生成Office文档的完整方案
Officegen终极指南:使用纯JavaScript生成Office文档的完整方案 Officegen是一个强大的JavaScript库,能够让开发者使用纯J
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考