JavaScript 事件处理
事件是用户与页面交互的桥梁——点击按钮、敲击键盘、滚动页面,每个动作都是一个事件(event)。JavaScript 通过事件监听器来响应用户操作。
addEventListener() — 监听事件
javascript
const button = document.querySelector('button');
button.addEventListener('click', () => {
console.log('按钮被点击了!');
}); 语法:元素.addEventListener('事件名', 回调函数)
同一个元素可以绑定多个监听器,它们会按注册顺序执行:
javascript
button.addEventListener('click', () => console.log('第一个'));
button.addEventListener('click', () => console.log('第二个'));
// 点击时输出:第一个 第二个 常用事件类型
鼠标事件
| 事件 | 触发时机 |
|---|---|
click | 鼠标单击(最常用) |
dblclick | 鼠标双击 |
mousedown | 按下鼠标键 |
mouseup | 松开鼠标键 |
mouseenter | 鼠标进入元素(不冒泡) |
mouseleave | 鼠标离开元素(不冒泡) |
mousemove | 鼠标在元素上移动 |
键盘事件
| 事件 | 触发时机 |
|---|---|
keydown | 键盘按下(持续按住会持续触发) |
keyup | 键盘松开 |
keypress | 字符键按下(已过时,用 keydown) |
表单事件
| 事件 | 触发时机 |
|---|---|
input | 输入框内容发生变化(每输入一个字符) |
change | 表单控件值改变并失去焦点 |
submit | 表单提交 |
focus | 元素获得焦点 |
blur | 元素失去焦点 |
其他常用事件
| 事件 | 触发时机 |
|---|---|
scroll | 页面或元素滚动 |
resize | 窗口大小改变 |
DOMContentLoaded | DOM 构建完成 |
load | 页面完全加载(含图片) |
事件对象
事件监听器的回调函数接收一个事件对象,包含事件的所有信息:
javascript
button.addEventListener('click', (event) => {
console.log(event.type); // "click"
console.log(event.target); // 被点击的元素
console.log(event.clientX); // 鼠标 x 坐标
console.log(event.clientY); // 鼠标 y 坐标
}); 键盘事件对象
javascript
document.addEventListener('keydown', (event) => {
console.log(event.key); // "a", "Enter", "Escape"
console.log(event.code); // "KeyA", "Enter", "Escape"(物理键位)
if (event.key === 'Escape') {
closeModal();
}
if (event.ctrlKey && event.key === 's') {
event.preventDefault(); // 阻止浏览器默认的保存行为
saveDocument();
}
}); 阻止默认行为
部分元素有默认行为(链接跳转、表单提交、右键菜单),可以用 preventDefault() 阻止:
javascript
// 阻止链接跳转(常用于单页应用)
link.addEventListener('click', (event) => {
event.preventDefault();
navigateTo(link.href);
});
// 阻止表单的默认提交
form.addEventListener('submit', (event) => {
event.preventDefault();
// 自行处理数据
const formData = new FormData(form);
}); 事件委托(Event Delegation)
当有大量子元素需要相同的事件处理时,将监听器绑定在父元素上,利用事件冒泡机制判断实际点击的目标:
javascript
// ❌ 为每个列表项绑定监听器(如果有 1000 个 li,太浪费)
document.querySelectorAll('li').forEach(li => {
li.addEventListener('click', handleClick);
});
// ✅ 事件委托:只在父元素绑定一个监听器
const list = document.querySelector('ul');
list.addEventListener('click', (event) => {
if (event.target.tagName === 'LI') {
console.log('点击了:', event.target.textContent);
}
}); 事件委托 + 新增元素
事件委托的另一个关键优势:即使是动态添加的子元素,也会被父元素的监听器捕获:
javascript
list.addEventListener('click', (event) => {
if (event.target.tagName === 'LI') {
event.target.classList.toggle('selected');
}
});
// 稍后动态添加的 li 也会响应点击
list.insertAdjacentHTML('beforeend', '<li>新增项目</li>'); 事件委托是 DOM 编程中最重要的性能优化模式之一。大幅减少监听器数量,天然支持动态元素。只要场景允许,优先使用事件委托而非逐个绑定。
移除监听器
javascript
function handleClick(event) {
console.log('点击');
}
button.addEventListener('click', handleClick);
button.removeEventListener('click', handleClick); // 移除 removeEventListener 需要传入同一个函数引用。匿名箭头函数无法被移除——removeEventListener('click', () => {...}) 永远不会工作,因为它是一个新的函数对象。