在操作 DOM 元素之前,先确保 HTML 结构已经完整解析完毕,这是前端开发中一条需要遵守的规则。如果 JavaScript 代码在 DOM 成型之前运行,试图去获取尚未存在的元素,或者给不存在的节点绑定事件,代码要么不起作用,要么直接抛出异常。
jQuery 的 $(document).ready() 就是用来解决这个时机问题的。它会在浏览器完成 DOM 树的构建后立刻执行内部的回调函数,而不用等待图片、样式表、iframe 等外部资源的加载完成。相比之下,原生 window.onload 必须等页面所有资源下载完毕才触发,这中间可能有明显的延迟。
为什么我不用 body 的 onload 属性而坚持用 jQuery 的 ready()?
两个原因。<body onload=""> 和 $(document).ready() 混用会导致行为不可预测——如果两者都定义了,执行顺序不一定如你所想。jQuery 官方文档也明确建议不要混用。window.onload 在整个页面只能绑定一个处理函数,重复赋值会覆盖之前的定义;而 $(document).ready() 可以多次调用,每次绑定的回调都会依次执行,互不影响。在模块化开发或多插件协作的页面中,这个差异的影响是决定性的。
语法
jQuery 提供了两种等价写法:
完整写法:
$(document).ready(function () {
// DOM 就绪后执行的代码
});
简写形式:
$(function () {
// DOM 就绪后执行的代码
});
两种写法在功能上没有区别。简写形式用 $() 直接包裹一个函数,这是 $(document).ready() 的语法糖。
参数说明:
-
function():必需参数,指定 DOM 就绪后要执行的回调函数。可以传入匿名函数或已定义的函数名。
课程知识要点
-
只等 DOM,不等资源:
ready()在 DOM 树构建完成后立即触发,图片、样式表等外部资源的加载状态不影响其执行时机。 -
可多次调用:同一个页面中可以写多个
$(document).ready()或$(function()),所有回调会按注册顺序依次执行。 -
**简写 ()是语法糖∗∗:‘()是语法糖∗∗:‘(function(){})
和$(document).ready(function(){})` 等价,前者在团队内部使用时简洁,后者对外部阅读者更友好。 -
不要和 body onload 混用:两者触发机制不同,同时使用会导致代码行为难以预测,也违反单一职责原则。
-
放在 head 还是 body 结尾?:使用
ready()后,脚本标签理论上可以放在<head>中而不影响逻辑。但从性能角度,把脚本标签放在关闭</body>之前依然是减少白屏时间的实践做法。
示例:DOM 就绪后绑定按钮事件并修改样式
下面这个例子展示了 ready() 的典型使用场景:页面加载后,在回调中为按钮绑定点击事件,点击后修改多个段落的样式。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>ready() 方法示例 · 编程学习</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
// 使用完整写法——阅读者容易理解这是一个 DOM 就绪回调
$(document).ready(function () {
// 在 DOM 就绪后才绑定事件,确保 button 元素一定存在
$("button").click(function () {
// 修改三个段落的各自样式
$("#p-title").css({
"font-size": "28px",
"color": "#1a73e8",
"background": "#fff3cd",
"font-weight": "bold"
});
$("#p-desc").css({
"font-size": "20px",
"font-weight": "bold",
"color": "#d93025"
});
$("#p-more").css({
"color": "#1a73e8"
});
});
});
</script>
</head>
<body>
<p id="p-title">欢迎来到编程学习社区</p>
<p id="p-desc">这是一个演示 $(document).ready() 方法的示例。</p>
<p id="p-more">点击下方按钮修改这些段落的样式。</p>
<button>修改样式</button>
</body>
</html>
页面加载后,点击按钮,三个段落分别应用不同的颜色和字体样式。由于所有 DOM 操作都在 ready() 回调内部或由它触发,不管脚本放在页面哪个位置都不存在目标元素尚未解析的问题。
简写形式的使用示例
如果你偏好简洁,简写形式的效果一致:
$(function () {
$("button").click(function () {
$("#p-title").css("color", "#1a73e8");
});
});
两种写法在同一个项目中可以混用,但如果团队里有新手,用完整写法能让代码意图更明确,降低理解门槛。
在多年开发中,我几乎给所有 jQuery 代码都包了一层 $(document).ready()。这层包装的成本很低但防御性很高——它保证你的选择器不会操作尚未解析的 DOM 节点,避免偶发性的 null 引用错误。
一个容易混淆的点是 $(document).ready() 和 $(window).on("load") 的区别。如果你需要操作图片尺寸、获取元素的实际宽高等依赖外部资源加载完毕的计算,应该用 $(window).on("load") 而不是 ready(),因为 ready 触发时图片可能还没加载完,尺寸信息还不准确。把两种事件用在正确的地方,能让页面的初始化逻辑在正确的时机运行。
如果你在维护老项目时同时看到了 $(document).ready() 和多处 window.onload,建议统一成前一种方式,并把所有初始化逻辑收敛到一处。这样执行顺序清晰可追溯,后续维护时不用在多个文件里反复确认谁先谁后。如果你的项目没有 jQuery 依赖,原生 DOMContentLoaded 事件可以实现和 ready() 相同的效果,在不需要引入整个 jQuery 库的情况下值得选用。