JavaScript 事件处理
事件是用户与页面交互的桥梁——点击按钮、敲击键盘、滚动页面,每个动作都是一个事件(event)。JavaScript 通过事件监听器来响应用户操作。
addEventListener() — 监听事件
javascript
const button = document.querySelector('#btn');
button.addEventListener('click', () => {
alert('按钮被点击了!');
}); html
<button id="btn">点我</button> 语法:元素.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
const button = document.querySelector('#btn');
button.addEventListener('click', (event) => {
alert('事件类型:' + event.type);
alert('目标元素:' + event.target.tagName);
alert('X 坐标:' + event.clientX);
alert('Y 坐标:' + event.clientY);
}); html
<button id="btn">点我</button> 键盘事件对象
javascript
document.addEventListener('keydown', (event) => {
alert('按下的键:' + event.key + '\n物理键位:' + event.code);
if (event.ctrlKey && event.key === 's') {
event.preventDefault();
alert('已阻止 Ctrl+S 默认行为');
}
}); html
<p>按下任意键查看事件信息。试试 Ctrl+S。</p> 阻止默认行为
部分元素有默认行为(链接跳转、表单提交、右键菜单),可以用 preventDefault() 阻止:
javascript
// 阻止链接跳转
document.querySelector('#myLink').addEventListener('click', (event) => {
event.preventDefault();
alert('链接跳转已被阻止');
});
// 阻止表单的默认提交
document.querySelector('#myForm').addEventListener('submit', (event) => {
event.preventDefault();
alert('表单提交已被阻止');
const data = new FormData(event.target);
alert('输入内容:' + data.get('text'));
}); html
<a id="myLink" href="https://example.com">点我跳转</a>
<form id="myForm">
<input name="text" placeholder="输入一些内容">
<button>提交</button>
</form> 事件委托(Event Delegation)
当有大量子元素需要相同的事件处理时,将监听器绑定在父元素上,利用事件冒泡机制判断实际点击的目标:
javascript
// 事件委托:只在父元素绑定一个监听器
const list = document.querySelector('ul');
list.addEventListener('click', (event) => {
if (event.target.tagName === 'LI') {
alert('点击了:' + event.target.textContent);
}
}); html
<ul>
<li>项目 1</li>
<li>项目 2</li>
<li>项目 3</li>
</ul> 事件委托 + 新增元素
事件委托的另一个关键优势:即使是动态添加的子元素,也会被父元素的监听器捕获:
javascript
const list = document.querySelector('ul');
list.addEventListener('click', (event) => {
if (event.target.tagName === 'LI') {
event.target.classList.toggle('selected');
}
});
// 稍后动态添加的 li 也会响应点击
list.insertAdjacentHTML('beforeend', '<li>新增项目(可点击)</li>'); html
<ul>
<li>现有项目 1</li>
<li>现有项目 2</li>
<li>现有项目 3</li>
</ul>
<style>
.selected { background: #ffeb3b; }
</style> 事件委托是 DOM 编程中最重要的性能优化模式之一。大幅减少监听器数量,天然支持动态元素。只要场景允许,优先使用事件委托而非逐个绑定。
移除监听器
javascript
function handleClick() {
alert('点击');
}
const button = document.querySelector('#btn');
button.addEventListener('click', handleClick);
// 3 秒后移除监听器
setTimeout(() => {
button.removeEventListener('click', handleClick);
alert('监听器已移除,点击按钮不再触发');
}, 3000); html
<button id="btn">点我(3 秒内点击有效)</button> removeEventListener 需要传入同一个函数引用。匿名箭头函数无法被移除——removeEventListener('click', () => {...}) 永远不会工作,因为它是一个新的函数对象。