document.readystate 的三个状态值分别代表:'loading'(文档正在解析)、'interactive'(dom 构建完成但外部资源可能未加载完,等效于 domcontentloaded)、'complete'(所有资源加载完毕,等效于 load 事件);它比 domcontentloaded 更底层,适合依赖图片尺寸、字体渲染等完整资源就绪的场景。

怎么用 document.readyState 判断页面是否真正就绪
很多人以为 DOMContentLoaded 触发就代表页面“能用了”,其实不然——它只说明 DOM 树构建完成,但图片、字体、样式表可能还在加载中。document.readyState 才是更底层的状态开关,有三个关键值:loading、interactive、complete。
真正适合执行初始化逻辑的时机是 complete,尤其当你的 JS 依赖渲染后的图片尺寸、Web Font 渲染结果或第三方脚本(如 analytics)时:
-
interactive时 DOM 可操作,但window.onload尚未触发,img元素的naturalWidth可能仍为 0 -
complete意味着所有资源(包括async脚本、defer脚本、img、link rel="stylesheet")均已加载完毕 - 不要只监听一次
readystatechange:状态可能从loading → interactive → complete跳变,需检查当前值而非仅靠事件触发
推荐写法:
function waitForComplete() {
if (document.readyState === 'complete') {
initApp();
} else {
document.addEventListener('readystatechange', () => {
if (document.readyState === 'complete') initApp();
});
}
}
为什么直接操作 display 比用 opacity 更可靠
用 opacity: 0 + transition 做 loading 遮罩,看似平滑,但容易在低端设备或高负载下卡顿,甚至出现“半透明遮罩下还能点按钮”的穿透问题。
真正稳的方案是切换 display 或 visibility,并配合 pointer-events: none:
-
display: none完全脱离渲染流,不占布局空间,也不响应任何事件 -
visibility: hidden保留占位,适合需要维持布局稳定的场景(比如防止按钮跳动) - 必须加
pointer-events: none到 loading 容器上,否则 iOS Safari 和部分安卓 WebView 仍会拦截点击事件 - 避免在 loading 元素里放
input或button,它们可能被键盘唤起或焦点捕获,导致不可见却可交互
fetch / axios 请求中 loading 状态怎么不出错
全局拦截器听着省事,实际踩坑最多:AbortError 不触发 response,网络中断没 error 抛出,Promise 被 catch 吞掉后 loading 就永远挂着。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
安全做法是每个请求都手动控制生命周期:
- 发起前:设 loading 状态为 true,并同步更新 UI(如按钮禁用 + 添加
disabled属性) - 无论成功、失败、取消,都必须走
.finally()关闭 loading —— 这是唯一能覆盖所有退出路径的钩子 - 不要依赖
.then().catch()双分支,因为fetch的 4xx/5xx 不进catch,得手动检查response.ok - axios 封装时,
config里传showLoading: true可以,但拦截器里不能只靠response和error,必须加request拦截器开 loading +finally关
示例关键片段:
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(r => r.json())
.catch(err => {
if (err.name === 'AbortError') return;
throw err;
})
.finally(() => hideLoading());
SPA 路由跳转时 loading 怎么覆盖完整空白期
只监听数据请求的 loading,会漏掉两个关键空白:组件挂载耗时(尤其是带大量计算的 Vue/React 组件)、代码分割 chunk 加载延迟(import() 动态导入)。
真实链路必须分层处理:
- 路由触发瞬间(如
router.push()或useNavigate()调用后)立即显示 loading —— 此时还没发请求,但用户已感知到导航意图 - 动态 import 完成后、组件
mounted或useEffect执行前,是第二个 loading 黄金窗口;可用defineAsyncComponent(Vue)或Suspense(React)兜底 - 服务端渲染(SSR)场景下,首屏 loading 必须在 HTML 返回前就生效,不能等 JS 加载完再控制 —— 这就是为什么最简方案要把 loading 元素写死在
开头 - 移动端要防“loading 闪一下就消失”:加最小显示时长(如 300ms),避免快速跳转造成视觉抖动
最容易被忽略的一点:loading 状态必须和用户操作强绑定。比如点击按钮跳转,loading 应该从按钮按下开始,而不是从 URL 改变开始 —— 否则手指离屏瞬间就结束,用户根本没感知到反馈。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










