jQuery 事件
页面要"活起来",靠的是响应用户的点击、输入、滚动。jQuery 把原生 addEventListener 简化成了 .on() 一套统一 API,还首创了"事件委托"这种杀手级模式。本章把事件系统讲透。
1. $(document).ready:jQuery 的启动入口
所有 jQuery 代码几乎都包在 $(document).ready() 里——它会在 DOM 解析完成时执行,不必等图片、视频这些慢资源。这能保证你操作元素时它已经存在。
// $(document).ready:DOM 解析完就执行,不等图片/视频加载
// 这是 jQuery 的"启动入口"
$(document).ready(function () {
console.log("DOM 就绪,可以安全操作元素了");
});
// 简写形式(完全等价,推荐)
$(function () {
console.log("同样在 DOM 就绪时执行");
});
// 与原生 DOMContentLoaded 等价,但 jQuery 帮你处理了:
// 1. 兼容所有浏览器(包括老 IE)
// 2. 可以注册多个回调(后注册的也会执行)
// 3. 如果 DOM 已经就绪,回调立即执行
// 对比:window.onload 要等所有资源(图片/CSS/iframe)加载完,慢得多
$(window).on("load", function () {
console.log("所有资源都加载完了");
});新手最容易踩的坑:把 script 写在 <head> 里且没用 ready,结果 $("#btn") 选不到元素(因为按钮还没解析)。要么用 ready 包起来,要么把 script 放到 </body> 之前。
2. .on():统一的事件绑定
从 jQuery 1.7 起,官方推荐所有事件绑定都用 .on()。旧的 .bind()、.live()、.delegate() 全部废弃——你只需记一个方法。
// .on() 是 jQuery 1.7+ 推荐的统一事件绑定方法
$("#btn").on("click", function () {
alert("被点了");
});
// 替代旧 API:.bind() / .live() / .delegate() 已被废弃,统一用 .on()
// 一次绑定多个事件,共用一个回调
$("#box").on("mouseenter mouseleave", function () {
$(this).toggleClass("hover");
});
// 一次绑定多个事件,各自不同回调
$("#box").on({
mouseenter: function () { $(this).addClass("hover"); },
mouseleave: function () { $(this).removeClass("hover"); },
click: function () { alert("点了"); },
});
// 带数据参数(回调里用 event.data 取)
$("#btn").on("click", { user: "Tom" }, function (e) {
console.log("hello " + e.data.user); // hello Tom
});注意第四个用法——带数据参数:通过 on 的第二个参数把数据塞进 event.data。这比闭包捕获变量更明确,也方便解绑。
3. 简写方法(语法糖)
jQuery 给常用事件起了简写名字:.click()、.change()、.submit()、.scroll() 等。它们本质上是 .on() 的语法糖,写起来更短。
// jQuery 给常用事件提供了简写方法,本质是 .on() 的语法糖
$("#btn").click(function () { /* ... */ });
$("#input").change(function () { /* ... */ });
$("#box").mouseenter(function () { /* ... */ });
$("#box").mouseleave(function () { /* ... */ });
$("#input").focus(function () { /* ... */ });
$("#input").blur(function () { /* ... */ });
$("#form").submit(function () { /* ... */ });
$(window).scroll(function () { /* ... */ });
$(window).resize(function () { /* ... */ });
// 触发事件(不带参 = 模拟触发)
$("#btn").click(); // 等于 .trigger("click")
// 注意:简写方法在新版 jQuery 3.x 仍可用,但官方推荐统一用 .on()
// 原因:.on() 更明确,且支持事件委托看到老代码用 .click()、.submit() 不必慌——它们没被废弃,照样能用。但新代码推荐统一用 .on(),因为只有 .on() 支持事件委托。
4. 事件委托(必学)
事件委托是 jQuery 最实用的模式之一——把监听绑在父元素上,后加进来的子元素也自动生效。动态列表、表格场景几乎必备。
// 事件委托:把监听绑在父元素,后加的子元素也生效
// 用法: .on(事件, 子选择器, 回调)
$("#list").on("click", "li", function () {
$(this).toggleClass("done");
});
// 为什么需要事件委托?
// 场景:#list 下有 100 个 <li>,你想给每个绑 click
// 方式 A: $("li").on("click", fn) 绑 100 个监听,占内存
// 方式 B: $("#list").on("click", "li", fn) 只绑 1 个监听,高效
// 另一个杀手锏:动态添加的元素也自动生效
$("#list").append("<li>新加的</li>");
// 方式 A 不会触发,方式 B 会触发 —— 这是事件委托最大的价值
// 原理:浏览器事件冒泡
// 子元素 <li> 被点击,事件会冒泡到父元素 <ul>
// jQuery 在 <ul> 上监听,检查 event.target 是否匹配 "li" 选择器
// 匹配才执行回调 —— 一次注册,永久生效
// 解绑事件
$("li").off("click"); // 解绑所有 click
$("li").off("click", specificHandler); // 只解绑指定回调原理是事件冒泡:子元素被点,事件会一路冒泡到父元素。jQuery 在父元素上监听,检查 event.target 是否匹配选择器,匹配才执行回调。好处有两个:性能(1000 个子元素只绑 1 个监听)和动态生效(后加的元素不用重新绑)。
5. 事件对象 event
回调函数的第一个参数是事件对象,包含触发源、坐标、按键等所有信息。常用的几个方法:preventDefault 阻止默认行为,stopPropagation 阻止冒泡。
// 事件对象 event:回调的第一个参数
$("#btn").on("click", function (event) {
// 1. 阻止默认行为(比如表单提交、链接跳转)
event.preventDefault();
// 2. 阻止事件冒泡(不往父元素传)
event.stopPropagation();
// 3. 同时阻止默认和冒泡(等价于上面两句)
event.preventDefault().stopPropagation();
// 或 return false; // jQuery 中 return false 等价于上面两句
return false;
// 4. 拿事件类型、目标元素
console.log(event.type); // "click"
console.log(event.target); // 真正被点的元素(DOM)
console.log(event.currentTarget); // 绑定监听的元素(DOM,等于 this)
console.log(event.which); // 鼠标键(1=左/2=中/3=右)或键盘码
console.log(event.pageX); // 鼠标相对页面左上的 X 坐标
console.log(event.pageY); // 鼠标相对页面左上的 Y 坐标
});
// 键盘事件常用:判断按了哪个键
$(document).on("keydown", function (e) {
if (e.which === 27) { // 27 是 ESC
console.log("ESC 按下了");
}
if (e.which === 13 && e.ctrlKey) { // Ctrl + Enter
console.log("提交!");
}
});jQuery 中 return false 等价于同时调用 preventDefault 和 stopPropagation——这和原生 JS 不同(原生只阻止默认)。在事件处理里写 return false 是 jQuery 的常见简写。
6. 主动触发与命名空间
有时你需要用代码主动触发事件,而不是等用户操作。jQuery 提供 .trigger(),还能用命名空间精细管理事件解绑。
// 主动触发事件
$("#btn").trigger("click"); // 触发 click + 执行默认行为
$("#btn").click(); // 简写
// 自定义事件(发布订阅模式)
$(document).on("app:ready", function (e, data) {
console.log("收到自定义事件,数据:", data);
});
$(document).trigger("app:ready", { user: "Tom" });
// 命名空间事件(精细控制解绑)
$("#btn").on("click.validation", fn1); // 命名空间 .validation
$("#btn").on("click.analytics", fn2); // 命名空间 .analytics
$("#btn").off("click.validation"); // 只解绑验证,不影响统计
$("#btn").off(".validation"); // 解绑所有 validation 命名空间
// 一次性事件
$("#btn").one("click", function () {
alert("只触发这一次");
});命名空间是大型项目的救星:同一元素绑了多个 click(验证、统计、AB 测试…),想解绑某个而不影响其他,用 click.命名空间 区分。.one() 则是"只触发一次"的语法糖,做引导提示、首次点击弹窗时很常用。
小结
jQuery 事件的核心就四件事:$(document).ready 启动、.on() 绑定、.off() 解绑、事件委托处理动态元素。把这四样吃透,遇到任何老 jQuery 代码都能读懂。下一篇我们正式开始操作 DOM——选中元素后,怎么改它的文字、样式、属性。
← 上一篇 jQuery 选择器
下一篇 jQuery DOM 操作 →