事件
事件
事件是用户与页面交互的桥梁:点击、输入、滚动、按键都会触发事件,JS 通过监听事件来响应用户操作。
这一篇讲事件的注册与解绑、事件类型、事件对象、事件流(冒泡/捕获)、事件委托。其中事件流和事件委托是重点,也是 JS 与 Java GUI(如 Swing 的监听器)最大的差异。
一、注册与解绑事件
1. 三种注册方式
1 | <!-- 方式一:HTML 属性(不推荐,结构和逻辑混在一起) --> |
1 | // 方式二:DOM 属性(同一事件只能绑一个,后写覆盖前写) |
⚠️
onclick方式后写会覆盖前一个;addEventListener可同时绑定多个,是标准做法。
2. 解绑 removeEventListener
1 | function handler() { |
⚠️ 关键坑:解绑必须传同一个函数引用。匿名函数无法解绑(
addEventListener里写() => {}就再也解不掉了)。需要解绑时,务必用命名函数。
二、事件类型
1. 鼠标事件
| 事件 | 触发时机 | 备注 |
|---|---|---|
click |
单击 | 最常用 |
dblclick |
双击 | |
mouseenter / mouseleave |
移入 / 移出 | 不冒泡,推荐 |
mouseover / mouseout |
移入 / 移出 | 冒泡,会受子元素影响 |
mousemove |
移动 | 配合坐标做拖拽 |
mousedown / mouseup |
按下 / 松开 | |
contextmenu |
右键 |
2. 键盘事件
| 事件 | 触发时机 |
|---|---|
keydown |
按下(推荐) |
keyup |
松开 |
keypress |
字符键按下(已废弃,少用) |
3. 表单事件
| 事件 | 触发时机 |
|---|---|
input |
每次输入(实时) |
change |
值改变且失焦后 |
submit |
表单提交 |
focus / blur |
获得 / 失去焦点 |
4. 页面事件
| 事件 | 触发时机 |
|---|---|
load |
页面全部加载完(含图片等资源) |
DOMContentLoaded |
DOM 构建完(比 load 早) |
scroll |
滚动 |
resize |
窗口大小改变 |
三、事件对象 event
事件回调的第一个参数就是事件对象 event(常简写 e):
1 | btn.addEventListener("click", function (e) { |
键盘事件的键信息:
1 | input.addEventListener("keydown", function (e) { |
两个最重要的方法:
1 | e.preventDefault(); // 阻止默认行为(链接跳转、表单提交、右键菜单) |
四、事件流(捕获与冒泡)
一次完整的事件传播分三个阶段:捕获阶段 → 目标阶段 → 冒泡阶段。
1 | // addEventListener 第三个参数控制在哪一阶段触发 |
1 | <div id="parent"> |
1 | // 点击 child 时,打印顺序: |
⚠️ 记忆点:默认(
false)是冒泡,事件从目标元素向上传到父元素,也是事件委托的基础。
阻止冒泡:e.stopPropagation() 让事件不再向上传播:
1 | child.addEventListener("click", function (e) { |
区分:
stopPropagation阻止传播,preventDefault阻止默认行为,两者互不影响。
五、事件委托(重点)
原理:利用事件冒泡,把监听器绑在父元素上,通过 event.target 判断实际点击的子元素。
1 | <ul id="list"> |
1 | // 不用委托:给每个 li 都绑定(li 多时性能差,且新增 li 要重新绑) |
委托的两大好处:
- 性能:只绑一个监听器,替代绑 N 个。
- 动态元素友好:后加入的子元素自动生效,无需重新绑定。
⚠️ target vs currentTarget(委托里最易混):
e.target:实际点到的元素(点谁是谁)。e.currentTarget:绑定监听器的元素(委托里是父元素ul)。事件委托判断目标时一定要用
e.target。
六、速查表
| 需求 | 写法 |
|---|---|
| 注册事件 | el.addEventListener("click", fn) |
| 解绑事件 | el.removeEventListener("click", fn)(要同名函数) |
| 阻止默认 | e.preventDefault() |
| 阻止冒泡 | e.stopPropagation() |
| 触发目标 | e.target |
| 绑定元素 | e.currentTarget |
| 按键名 | e.key |
| 鼠标坐标 | e.clientX / e.clientY |
| 捕获阶段 | addEventListener("click", fn, true) |
| 事件委托 | 父元素监听 + e.target 判断 |
七、复习要点
- 注册事件用
addEventListener(可绑多个),解绑要同名函数引用(匿名函数解不掉)。 - 常用事件:鼠标
click/mouseenter/mousemove、键盘keydown、表单input/change/submit、页面load/DOMContentLoaded/scroll。 e.target是实际触发元素,e.currentTarget是绑定元素;preventDefault阻止默认,stopPropagation阻止冒泡。- 事件流三阶段:捕获 → 目标 → 冒泡,默认在冒泡阶段触发。
- 事件委托:监听父元素 +
e.target判断,省性能、支持动态元素。 - 忘了某个事件或属性,回本文对应小节查示例即可。
下一篇预告:BOM 与本地存储——window、location、history、navigator、localStorage/sessionStorage。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Yang's Blog!