jQuery 作为前端经典的 DOM 事件处理库,通过简洁的 API 封装了原生 JS 事件体系,大幅简化了事件绑定、解绑和委托操作。以下是梳理的常用事件类型及核心注意事项
一、jQuery 事件绑定的核心方式
先明确基础绑定语法,后续事件类型均基于这些方式使用:
| 绑定方式 | 语法示例 | 适用场景 |
|---|---|---|
| 直接绑定 | $('selector').click(function(){}) |
静态 DOM 元素、简单事件 |
| on () 绑定(推荐) | $('selector').on('click', fn) |
动态 DOM、多事件、事件委托 |
| 事件委托 | $('parent').on('click', 'child', fn) |
动态生成的子元素 |
| 解绑事件 | $('selector').off('click', fn) |
移除指定事件监听 |
| 一次性事件 | $('selector').one('click', fn) |
事件仅触发一次(如弹窗关闭) |
核心推荐:优先使用
on(),它兼容所有事件类型,支持动态元素和事件委托,是 jQuery 1.7+ 后的统一事件 API。
二、常用事件类型分类及示例
1. 鼠标事件(最常用)
处理鼠标触发的交互,覆盖点击、悬浮、滚动等场景:
| 事件类型 | 触发时机 | 示例代码 |
|---|---|---|
click |
鼠标左键单击 | $('.btn').on('click', () => { alert('点击按钮'); }) |
dblclick |
鼠标左键双击 | $('.box').dblclick(() => { $(this).toggleClass('active'); }) |
mouseenter |
鼠标进入元素(无冒泡) | $('.nav-item').mouseenter(() => { $(this).find('.submenu').show(); }) |
mouseleave |
鼠标离开元素(无冒泡) | $('.nav-item').mouseleave(() => { $(this).find('.submenu').hide(); }) |
mouseover |
鼠标进入元素 / 子元素(有冒泡) | (慎用,优先用 mouseenter) |
mouseout |
鼠标离开元素 / 子元素(有冒泡) | (慎用,优先用 mouseleave) |
mousedown |
鼠标按键按下(左 / 中 / 右) | $('.canvas').mousedown((e) => { if(e.which === 3) alert('右键按下'); }) |
mouseup |
鼠标按键松开 | $('.canvas').mouseup(() => { console.log('鼠标松开'); }) |
contextmenu |
鼠标右键单击(禁用右键菜单常用) | $('body').on('contextmenu', (e) => e.preventDefault()); |
关键区别:
mouseenter/mouseleave不冒泡(仅触发自身),mouseover/mouseout冒泡(进入子元素也触发),开发中优先选前者避免不必要的触发。
2. 键盘事件
处理键盘按键交互,多用于表单、快捷键场景:
| 事件类型 | 触发时机 | 示例代码 |
|---|---|---|
keydown |
按键按下(含功能键,先触发) | $('#input').keydown((e) => { if(e.keyCode === 13) alert('回车按下'); }) |
keyup |
按键松开 | $('#input').keyup(() => { console.log('输入内容:', $(this).val()); }) |
keypress |
按键按下(仅字符键,已废弃) | (建议用 keydown/keyup 替代) |
注意:
keyCode已逐步被key替代(如e.key === 'Enter'),兼容性更好:js
$('#input').keydown((e) => { if (e.key === 'Enter') { // 替代 keyCode === 13 console.log('回车触发'); } });
3. 表单事件
处理表单元素交互,核心用于表单提交、输入、选择:
| 事件类型 | 触发时机 | 示例代码 |
|---|---|---|
submit |
表单提交(按钮 / 回车) | $('form').on('submit', (e) => { e.preventDefault(); // 阻止默认提交 }) |
change |
表单值改变且失焦(下拉 / 复选 / 输入) | $('#select').change(() => { console.log('选中值:', $(this).val()); }) |
input |
输入框实时输入(替代 keyup) | $('#username').on('input', () => { console.log('实时输入:', $(this).val()); }) |
focus |
元素获得焦点(无冒泡) | $('input').focus(() => { $(this).addClass('focused'); }) |
blur |
元素失去焦点(无冒泡) | $('input').blur(() => { $(this).removeClass('focused'); }) |
select |
文本框内容被选中 | $('#content').select(() => { alert('选中了文本'); }) |
核心区别:
change是「失焦后值变化」触发,input是「实时输入」触发,表单校验优先用input。
4. 文档 / 窗口事件
处理页面加载、大小调整、滚动等全局事件:
| 事件类型 | 触发时机 | 示例代码 |
|---|---|---|
ready |
DOM 加载完成(替代 window.onload) | $(document).ready(() => { console.log('DOM 加载完成'); }) // 简写:$(fn) |
load |
页面 / 资源(图片 /iframe)加载完成 | $(window).load(() => { console.log('所有资源加载完成'); }) |
resize |
窗口大小调整 | $(window).on('resize', () => { console.log('窗口宽度:', $(window).width()); }) |
scroll |
页面 / 元素滚动 | $(window).scroll(() => { if($(window).scrollTop() > 100) { $('.backtop').show(); } }) |
unload |
页面卸载(关闭 / 刷新) | $(window).on('unload', () => { alert('页面即将卸载'); }) |
关键:
$(document).ready()比window.onload执行更早(DOM 就绪即可,无需等资源加载),是 jQuery 入口函数的首选。
5. 其他常用事件
| 事件类型 | 触发时机 | 示例代码 |
|---|---|---|
focusin |
元素 / 子元素获得焦点(有冒泡) | $('.form-group').focusin(() => { $(this).addClass('active'); }) |
focusout |
元素 / 子元素失去焦点(有冒泡) | $('.form-group').focusout(() => { $(this).removeClass('active'); }) |
toggle |
点击事件切换(已废弃,手动实现) | (替代方案:$(this).toggleClass('show');) |
三、核心注意事项(避坑关键)
1. 动态元素事件绑定(最易踩坑)
问题 :直接绑定的事件对「动态生成的 DOM」无效(如 ajax 加载的按钮)。解决方案 :使用事件委托(将事件绑定到静态父元素,委托给动态子元素):
// 错误写法:动态生成的 .btn 无事件
$('.btn').click(() => { ... });
// 正确写法:委托给静态父元素(如 body、.container)
$('body').on('click', '.btn', () => {
console.log('动态按钮点击生效');
});
原则:委托的父元素越接近目标元素越好(避免 body 全局委托影响性能)。
2. 事件重复绑定(导致多次触发)
问题 :多次执行绑定代码(如在循环 / 回调中),导致同一元素绑定多个相同事件。解决方案:
-
绑定前先解绑:
$('.btn').off('click').on('click', fn); -
使用一次性事件:
$('.btn').one('click', fn); -
用命名空间隔离事件:
// 绑定带命名空间的事件 $('.btn').on('click.myNamespace', () => { ... }); // 仅解绑该命名空间的事件(不影响其他 click 事件) $('.btn').off('click.myNamespace');
3. 阻止默认行为与事件冒泡
场景:点击链接不跳转、表单不提交、事件不向上传播。
$('a').on('click', (e) => {
e.preventDefault(); // 阻止默认行为(如链接跳转)
e.stopPropagation(); // 阻止事件冒泡(如父元素的 click 事件)
// 简写:return false; (同时阻止默认行为+冒泡)
});
注意:
return false=e.preventDefault() + e.stopPropagation(),按需选择,避免滥用。
4. this 指向问题
规则 :事件回调中 this 指向触发事件的原生 DOM 元素,需转为 jQuery 对象才能用 jQuery 方法:
$('.box').on('click', function() {
// 错误:this 是原生 DOM,无 addClass 方法
// this.addClass('active');
// 正确:转为 jQuery 对象
$(this).addClass('active');
});
箭头函数注意:箭头函数中
this指向外层作用域(非 DOM 元素),事件回调优先用普通函数。
5. 事件解绑的注意事项
-
解绑无参
off():移除元素所有事件(慎用); -
解绑指定事件:
off('click')移除所有 click 事件; -
解绑指定回调:需绑定具名函数(匿名函数无法解绑):
// 具名函数 function handleClick() { console.log('点击'); } // 绑定 $('.btn').on('click', handleClick); // 解绑(仅该函数) $('.btn').off('click', handleClick);
6. 性能优化
-
避免全局事件委托(如
$(document).on('click', '.btn', fn)),优先绑定到最近的静态父元素; -
滚动 /resize 事件添加节流:避免高频触发(如 resize 每秒仅执行 1 次):
let timer = null; $(window).on('resize', () => { clearTimeout(timer); timer = setTimeout(() => { console.log('resize 节流执行'); }, 200); }); -
页面卸载前解绑事件:避免内存泄漏(尤其单页应用):
$(window).on('unload', () => { $('.btn').off('click'); $(window).off('resize scroll'); });
7. 兼容与废弃事件
keypress/toggle已废弃,优先用keydown/keyup/ 手动切换类;load/unload在移动端部分浏览器兼容性差,可结合原生addEventListener;- jQuery 3.x 中
ready事件不再支持$(fn)以外的写法(如$(document).ready(fn)仍支持)。
四、注意
- 事件绑定优先用
on():兼容动态元素、支持委托,是 jQuery 事件的统一入口; - 动态元素必须用事件委托:绑定到静态父元素,避免事件失效;
- 避免重复绑定:解绑后再绑定、用命名空间 / 一次性事件;
- this 指向要转换 :事件回调中
$(this)才是 jQuery 对象; - 高频事件加节流:scroll/resize 等事件需控制触发频率;
- 按需阻止默认行为 / 冒泡 :避免
return false滥用。