HTML5 入门教程
事件处理基础
本教程共 110 篇 · 第 103 篇 · 更新于 2026-07-28 · 约 5 分钟阅读
HTML5HTML5 入门教程事件事件监听事件冒泡事件委托
103. 事件处理基础
本节目标:理解浏览器事件模型,掌握 addEventListener 的用法,了解事件冒泡、捕获和事件委托的原理。
什么是事件
事件是浏览器发出的通知:用户点击了、页面加载完成了、输入框内容变了……你的 JS 代码可以”监听”这些事件,然后做出响应。
三种监听方式
1. HTML 事件属性(不推荐)
<button onclick="alert('我被点了')">点我</button>
把 JS 写在 HTML 里,又乱又难维护。不要用这种方式。
2. DOM 事件属性(有局限)
button.onclick = function () {
alert("我被点了");
};
问题是只能绑一个。第二次赋值会覆盖第一次。
3. addEventListener(推荐)
button.addEventListener("click", function () {
alert("我第一次被点");
});
button.addEventListener("click", function () {
alert("我也能被点");
});
两个都会执行。这是标准做法。
addEventListener 详解
element.addEventListener(type, listener, options);
| 参数 | 说明 |
|---|---|
type | 事件类型:click、keydown、submit 等 |
listener | 触发时执行的函数 |
options | 可选配置:capture、once、passive |
once:只执行一次
button.addEventListener("click", function () {
alert("我只执行一次");
}, { once: true });
事件对象
事件触发时,浏览器会把”事件对象”传给监听器:
element.addEventListener("click", function (event) {
console.log(event.type); // "click"
console.log(event.target); // 被点击的元素
console.log(event.currentTarget); // 绑了监听器的元素
console.log(event.clientX); // 鼠标 X 坐标
console.log(event.clientY); // 鼠标 Y 坐标
});
常用属性:
| 属性 | 说明 |
|---|---|
event.type | 事件类型 |
event.target | 触发事件的元素 |
event.currentTarget | 绑了监听的元素 |
event.preventDefault() | 阻止默认行为 |
event.stopPropagation() | 阻止事件冒泡 |
event.stopImmediatePropagation() | 阻止冒泡 + 阻止同元素其他监听器 |
事件冒泡和捕获
事件传播分三个阶段:
- 捕获阶段:从
window一路向下到目标元素 - 目标阶段:到达实际被点击的元素
- 冒泡阶段:从目标元素一路向上回到
window
window → document → html → body → div → button(目标)→ div → body → ...
捕获阶段 冒泡阶段
默认情况下,addEventListener 监听的是冒泡阶段。
// 第三个参数设为 true,监听捕获阶段
parent.addEventListener("click", handler, true);
事件委托:省事件监听器的利器
如果一个父元素下有大量子元素,每个子元素都绑监听器很浪费。
更好的做法:在父元素上绑一个监听器,利用冒泡原理判断是哪个子元素被点的。
<ul id="list">
<li data-id="1">项目一</li>
<li data-id="2">项目二</li>
<li data-id="3">项目三</li>
</ul>
<script>
document.getElementById("list").addEventListener("click", function (e) {
if (e.target.tagName === "LI") {
console.log("点了:", e.target.dataset.id);
}
});
</script>
事件委托的好处:
- 只需要一个监听器,性能更好
- 新加子元素不需要重新绑定
- 内存占用少
Tip列表、表格、导航菜单这类重复性元素多的场景,用事件委托是最佳实践。
移除监听器
function handleClick() {
console.log("clicked");
}
element.addEventListener("click", handleClick);
// 移除(必须用同一个函数引用)
element.removeEventListener("click", handleClick);
注意:匿名函数无法移除。所以想以后能移除的监听器,用命名函数。
常用事件速查
| 事件 | 触发时机 |
|---|---|
click | 点击 |
dblclick | 双击 |
mousedown / mouseup | 鼠标按下 / 释放 |
mouseenter / mouseleave | 鼠标移入 / 移出(不冒泡) |
mouseover / mouseout | 鼠标移入 / 移出(冒泡) |
mousemove | 鼠标移动 |
keydown / keyup / keypress | 键盘事件 |
focus / blur | 获得 / 失去焦点 |
input | 输入内容变化 |
change | 值变化且失去焦点 |
submit | 表单提交 |
scroll | 滚动 |
load / DOMContentLoaded | 加载完成 |
Note移动端用
touchstart、touchmove、touchend等触摸事件。但现代浏览器也支持 Pointer Events(pointerdown、pointermove),更统一。
阻止默认行为
有些元素有默认行为:链接跳转、表单提交、右键菜单……
// 阻止链接跳转
a.addEventListener("click", function (e) {
e.preventDefault();
});
// 阻止表单提交
form.addEventListener("submit", function (e) {
e.preventDefault();
// 手动处理提交逻辑
});
Warning
preventDefault()只阻止默认行为,不阻止事件传播。stopPropagation()只阻止传播,不阻止默认行为。两者互不干扰。