事件、事件模型、事件流与委托
JavaScript 事件是浏览器与用户交互的核心机制:用户操作(点击、输入)或浏览器状态变化(加载、resize)会触发事件,通过监听执行逻辑。
常用事件
shell
鼠标:click, dblclick, mouseover, mouseout, mousemove
键盘:keydown, keyup, keypress
表单:submit, change, focus, blur
窗口:load, resize, scroll
触摸:touchstart, touchmove, touchend事件模型
JS 历史上三种绑定方式(现代开发以标准模型为主):
shell
1. 原始模型:el.onclick = function() {}
特点:同类型只能绑一个,且不支持捕获阶段
2. 标准模型:el.addEventListener('click', fn, useCapture)
特点:可绑多个;第三参 true 表示捕获阶段执行,false/省略为冒泡阶段(默认)
3. IE 老旧模型(IE8−):attachEvent —— 仅存考古意义事件流(捕获 · 目标 · 冒泡)
shell
# 何为事件流
DOM 树形结构下,父子都监听同一类事件时需约定传播顺序——即事件流。
# 三个阶段
捕获:从外向目标(document → html → … → 目标)
目标:到达触发节点
冒泡:从目标向外回到 document/window(多数 DOM 事件默认冒泡)
典型路径简述:window → document → html → body → … → target → … → window
addEventListener 默认在冒泡阶段触发;第三个参数 true 则命中捕获阶段。
# 阻止
e.stopPropagation():停止继续传播(捕获或冒泡链上生效)
e.stopImmediatePropagation():同节点上其余监听也不再执行(标准 API)
e.preventDefault():取消浏览器默认行为(如表单提交跳转、a 跳转、右键菜单)
# 事件委托(代理)
原理:依赖冒泡,把多个子元素的响应集中到父元素,在回调里通过 e.target / e.currentTarget 判断真实来源。
优点:监听数少、动态插入子节点不需重新绑、内存更省。
注意:仅能委托「会冒泡」的事件(click、mousedown/up、部分键盘事件等);不要无脑挂 document;需在回调内精确甄别 target。preventDefault 示例
js
document.querySelector('form').addEventListener('submit', (event) => {
event.preventDefault();
// 再走 AJAX 提交
});
document.querySelector('a').addEventListener('click', (event) => {
event.preventDefault();
});
document.addEventListener('contextmenu', (event) => {
event.preventDefault();
});事件循环与本节的关系(边界说明)
此处「事件」指 DOM 交互事件;它们在回调进入队列后,由 JavaScript 事件循环(宏任务 / 微任务、渲染节拍)调度执行。输出顺序与时序题 请单独阅读:异步/异步 API/01、事件循环、以及本目录「实战考察」篇。
