当前位置: 首页 > news >正文

页面加载时机解密:window.onload vs document.ready

⏱️ 页面加载时机解密:window.onloadvsdocument.ready

🤔 为什么需要区分加载时机?

浏览器加载一个网页,并不是“一瞬间”全部完成的,而是一个分阶段的过程:

  1. 解析 HTML:构建 DOM 树(文档对象模型)。
  2. 加载资源:下载 CSS、JS、图片、视频等外部资源。
  3. 渲染页面:将 DOM 和 CSSOM 结合,绘制到屏幕上。

如果在错误的时机操作 DOM(比如元素还没生成就去获取它),代码就会报错。因此,我们需要知道“什么时候可以安全地操作 DOM”以及“什么时候所有资源都准备好了”

通俗比喻
想象你在装修新房(加载网页):

  • document.ready(DOMContentLoaded):硬装结束。墙壁刷好了,地板铺好了,家具(DOM 元素)都到位了。你可以开始布置软装(绑定事件、操作 DOM),不需要等待快递(图片/视频)送达
  • window.onload:全屋就绪。不仅硬装好了,连网购的大冰箱、沙发、装饰画(图片、iframe 等资源)全都送货上门并摆放完毕。这时候才是真正的“完全加载”

📂 目录

  1. 🛠️ 两大主角介绍
  2. ⚖️ 核心区别:触发时机大不同
  3. 💻 代码实战:一看就懂
  4. 🔄 现代替代方案:原生 JS 怎么做?
  5. ⚠️ 常见陷阱与最佳实践
  6. 💡 总结

1. 🛠️ 两大主角介绍

document.ready(jQuery 概念)

注意:$(document).ready()是 jQuery 库提供的方法。在原生 JavaScript 中,对应的事件是DOMContentLoaded

  • 含义:当初始的 HTML 文档被完全加载和解析之后触发,无需等待样式表、图像和子框架完成加载。
  • 特点:速度快,通常在页面视觉呈现初期就会触发。
  • 逻辑:“DOM 树建好了,我可以开始操作元素了!”

window.onload

  • 含义:当整个页面及所有依赖资源(如图片、CSS、JS、iframe 等)都加载完毕后触发。
  • 特点:速度较慢,必须等到所有资源下载完成。
  • 逻辑:“所有东西都到位了,我可以开始计算图片尺寸、进行复杂布局了!”

2. ⚖️ 核心区别:触发时机大不同

特性document.ready(DOMContentLoaded)window.onload
触发时机DOM 解析完成后立即触发所有资源(图片、样式等)加载完成后触发
等待图片?❌ 不等待✅ 等待
执行速度🚀🐢(取决于资源大小)
适用场景大多数 DOM 操作、事件绑定、初始化插件需要获取图片宽高、依赖资源完全加载的场景
原生对应document.addEventListener('DOMContentLoaded', ...)window.addEventListener('load', ...)

黄金法则

  • 90% 的业务逻辑(如点击事件、表单验证、动态内容填充)应该使用document.ready/DOMContentLoaded,因为用户体验更流畅,无需等待大图加载。
  • 只有当你确实需要依赖图片尺寸外部资源完全就绪时,才使用window.onload

3. 💻 代码实战:一看就懂

假设我们有一个包含大图片的页面:

<imgsrc="huge-image.jpg"id="myImg"/><divid="content">Hello</div>

场景一:使用document.ready(jQuery 风格)

// jQuery 写法$(document).ready(function(){console.log("DOM 准备好了!");// ✅ 可以安全获取 divconsole.log(document.getElementById("content").innerText);// ⚠️ 此时图片可能还没加载完constimg=document.getElementById("myImg");console.log(img.width);// 可能是 0,或者自然宽度,取决于浏览器实现});

场景二:使用window.onload

// 原生 JS 写法window.onload=function(){console.log("所有资源加载完毕!");// ✅ 此时图片肯定加载完了constimg=document.getElementById("myImg");console.log(img.width);// 肯定是图片的真实渲染宽度};

执行顺序演示

如果同时注册这两个事件,控制台输出顺序一定是:

  1. "DOM 准备好了!"(先执行)
  2. (等待图片下载…)
  3. "所有资源加载完毕!"(后执行)

4. 🔄 现代替代方案:原生 JS 怎么做?

现在的项目很少强制依赖 jQuery,我们应该掌握原生的写法。

✅ 推荐:DOMContentLoaded

这是document.ready的原生等价物。

document.addEventListener("DOMContentLoaded",function(){console.log("HTML 文档已完全加载和解析");// 在这里执行你的初始化代码initApp();});

✅ 备选:load事件

这是window.onload的现代写法(建议使用addEventListener而不是直接赋值window.onload,以避免覆盖其他监听器)。

window.addEventListener("load",function(){console.log("页面及其所有资源(图片、样式表等)已完全加载");// 在这里执行依赖资源的代码calculateLayout();});

💡 进阶:defer属性

如果你将<script>标签放在<head>中,可以使用defer属性,它的效果类似于DOMContentLoaded,但更优雅:

<head><!-- 脚本会异步下载,但在 HTML 解析完成后、DOMContentLoaded 触发前执行 --><scriptsrc="app.js"defer></script></head>

优势:无需在 JS 里写监听器,脚本自动在 DOM 就绪时执行,且保持执行顺序。


5. ⚠️ 常见陷阱与最佳实践

❌ 陷阱 1:在head中直接操作 DOM

<head><script>// ❌ 错误:此时 body 还没解析,getElementById 返回 nulldocument.getElementById("demo").innerHTML="Hello";</script></head><body><divid="demo"></div></body>

✅ 修正

  1. 将脚本移到</body>之前。
  2. 或者使用DOMContentLoaded监听。
  3. 或者给 script 添加defer

❌ 陷阱 2:混用window.onload赋值

// ❌ 危险:第二次赋值会覆盖第一次window.onload=functionA;window.onload=functionB;// functionA 永远不会执行!

✅ 修正:始终使用addEventListener

window.addEventListener("load",functionA);window.addEventListener("load",functionB);// 两个都会执行

❌ 陷阱 3:误以为ready等待图片

很多新手以为$(document).ready()后图片就能拿到宽高,结果发现是 0。请记住:Ready 不等图片!


💡 总结

特性DOMContentLoaded(即 ready)window.onload(即 load)
核心含义DOM 树构建完成页面所有资源加载完成
速度
能否操作 DOM✅ 能✅ 能
能否获取图片尺寸❌ 不一定✅ 能
推荐程度🌟🌟🌟🌟🌟 (绝大多数场景)🌟🌟 (特定场景)

🚀 博主寄语
理解加载时机,是写出高性能、无 Bug 前端代码的基础。

记住口诀
DOM 就绪用 Ready (DOMContentLoaded),
资源全齐用 Load (onload)。
脚本放置加 Defer,
覆盖监听要避免。

希望这篇文档能帮你彻底厘清window.onloaddocument.ready的区别!如果有疑问,欢迎在评论区留言。👇

喜欢这篇文章吗?记得点赞、收藏、转发哦!❤️

http://www.jsqmd.com/news/781451/

相关文章:

  • 基于ScallopBot理念构建模块化Discord机器人:从架构设计到实战开发
  • 基于机器学习的软件工程自动化实践:从Bug分类到测试优化
  • 2026年全屋定制性价比排名,铂匠装饰值得信赖 - 工业推荐榜
  • OpenClaw审计数据可视化工具:本地时间线查看器与事件记录工作区
  • 轻量级视觉语言模型miniclawd:从原理到实践,消费级硬件可复现
  • NB-IoT核心技术解析与传输优化实践
  • RNN实战指南:从原理到LSTM/GRU优化技巧
  • 别再只用CNN了!对比GoogLeNet、ResNet等5大预训练模型,看哪个在垃圾分类任务上更胜一筹
  • 别再硬扛大变形了!Fluent动网格Remeshing+Spring Smoothing保姆级配置指南(附UDF)
  • 基于插件化架构的命令行任务聚合工具设计与实现
  • Llama-3.2V-11B-cot实操手册:自定义REASONING深度(1~5步)控制推理粒度
  • 7大AI提示工程技术提升语言模型输出质量
  • RS信号发生器仿真模式应用与兼容性解决方案
  • 构建高效学习系统:从元学习到技能内化的实践指南
  • MDK5项目瘦身指南:如何从Pack里精准提取emWin库文件,告别臃肿的中间件安装
  • Keil User命令栏的隐藏玩法:除了生成Bin文件,你还能用它做这些事
  • 开源类Claude大模型本地部署:从架构解析到实战调优
  • 别再乱码了!从ASCII到Base64,5分钟搞懂程序员必知的字符编码(附Python实战代码)
  • AI赋能Figma原生批注:自动化设计文档生成与智能标注实践
  • 网页自定义光标实战:从CSS基础到像素动画实现
  • 保姆级教程:用Python和C++分别解析ROS Bag文件,到底哪个更适合你?
  • Qwen3-4B-Instruct一文详解:instruction tuning对长文本任务的增益分析
  • 机器学习回归模型优化:从线性回归到逻辑回归的实践
  • GLake:蚂蚁开源GPU内存与IO优化库,提升大模型训练推理效率
  • 别再只会用/bin/bash了!Docker容器报错‘OCI runtime exec failed‘的三种排查思路与终极解法
  • AI播客生成器:从文本到对话式音频的自动化实践
  • 从SDK解压到镜像烧录:爱芯元智AX630A Linux系统编译与eMMC烧写全流程实战
  • AI智能体工作流编排:从单体到流水线的工程实践
  • macOS防休眠工具:模拟鼠标移动保持系统活跃的原理与实践
  • 英语阅读_Li Mings birthday