事件处理
事件是浏览器或用户与网页交互时发生的动作,如点击、滚动、按键等。JavaScript可以通过事件处理来响应用户操作。
事件流
事件流描述了事件在DOM树中传播的过程,主要有两种模型:
冒泡模型
事件从触发元素开始,逐级向上传播到文档根节点:
text
元素 → 父元素 → ... → body → html → document
捕获模型
事件从文档根节点开始,逐级向下传播到触发元素:
text
document → html → body → ... → 父元素 → 元素
事件处理方式
1. HTML属性方式
直接在HTML标签中添加事件属性:
html
<button onclick="handleClick()">点击我</button>
<script>
function handleClick() {
alert('按钮被点击了');
}
</script>
2. DOM属性方式
通过JavaScript设置元素的事件属性:
javascript
const button = document.getElementById('myButton');
button.onclick = function() {
alert('按钮被点击了');
};
// 移除事件处理程序
button.onclick = null;
3. addEventListener方法
推荐使用的方式,可以添加多个事件处理程序:
javascript
const button = document.getElementById('myButton');
// 添加事件监听器
button.addEventListener('click', function() {
alert('按钮被点击了');
});
// 添加另一个事件监听器
button.addEventListener('click', function() {
console.log('按钮点击事件被记录');
});
// 移除事件监听器(需要使用命名函数)
function handleClick() {
alert('点击处理');
}
button.addEventListener('click', handleClick);
button.removeEventListener('click', handleClick);
捕获与冒泡
javascript
const parent = document.getElementById('parent');
const child = document.getElementById('child');
// 捕获阶段执行(第三个参数为true)
parent.addEventListener('click', function() {
console.log('父元素捕获');
}, true);
// 冒泡阶段执行(默认,第三个参数为false)
parent.addEventListener('click', function() {
console.log('父元素冒泡');
}, false);
child.addEventListener('click', function() {
console.log('子元素冒泡');
});
// 点击子元素时的执行顺序:
// 1. 父元素捕获
// 2. 子元素冒泡
// 3. 父元素冒泡
事件对象
事件处理程序会接收一个事件对象作为参数,包含事件的详细信息:
javascript
const button = document.getElementById('myButton');
button.addEventListener('click', function(event) {
console.log(event.type); // 事件类型:"click"
console.log(event.target); // 事件目标元素:按钮
console.log(event.currentTarget); // 当前处理事件的元素:按钮
console.log(event.clientX, event.clientY); // 点击位置相对于浏览器窗口
console.log(event.pageX, event.pageY); // 点击位置相对于文档
console.log(event.screenX, event.screenY); // 点击位置相对于屏幕
});
事件类型
鼠标事件
javascript
// 点击事件
element.addEventListener('click', handler);
element.addEventListener('dblclick', handler); // 双击
// 鼠标移动
element.addEventListener('mousedown', handler); // 鼠标按下
element.addEventListener('mouseup', handler); // 鼠标释放
element.addEventListener('mousemove', handler); // 鼠标移动
element.addEventListener('mouseover', handler); // 鼠标进入
element.addEventListener('mouseout', handler); // 鼠标离开
element.addEventListener('mouseenter', handler); // 鼠标进入(不冒泡)
element.addEventListener('mouseleave', handler); // 鼠标离开(不冒泡)
键盘事件
javascript
document.addEventListener('keydown', handler); // 按键按下
document.addEventListener('keyup', handler); // 按键释放
document.addEventListener('keypress', handler); // 按键按下并释放
// 键盘事件对象
document.addEventListener('keydown', function(event) {
console.log(event.key); // 按键名称:"a", "Enter", "Shift"
console.log(event.keyCode); // 按键代码(数字)
console.log(event.ctrlKey); // Ctrl键是否按下
console.log(event.shiftKey); // Shift键是否按下
console.log(event.altKey); // Alt键是否按下
});
表单事件
javascript
const form = document.getElementById('myForm');
const input = document.getElementById('myInput');
form.addEventListener('submit', function(event) {
event.preventDefault(); // 阻止表单默认提交行为
// 表单处理逻辑
});
input.addEventListener('input', function() {
console.log('输入内容:', this.value);
});
input.addEventListener('change', function() {
console.log('输入内容已更改:', this.value);
});
input.addEventListener('focus', function() {
console.log('输入框获得焦点');
});
input.addEventListener('blur', function() {
console.log('输入框失去焦点');
});
窗口事件
javascript
// 页面加载完成
window.addEventListener('load', function() {
console.log('页面加载完成');
});
// DOM加载完成
document.addEventListener('DOMContentLoaded', function() {
console.log('DOM加载完成');
});
// 窗口大小改变
window.addEventListener('resize', function() {
console.log('窗口大小改变');
});
// 窗口滚动
window.addEventListener('scroll', function() {
console.log('窗口滚动');
});
事件委托
利用事件冒泡原理,在父元素上监听事件,处理子元素的事件:
html
<ul id="myList">
<li>项目1</li>
<li>项目2</li>
<li>项目3</li>
</ul>
<script>
const list = document.getElementById('myList');
list.addEventListener('click', function(event) {
if (event.target.tagName === 'LI') {
console.log('点击了项目:', event.target.textContent);
}
});
</script>
事件委托的优点:
- 减少事件监听器的数量
- 动态添加的子元素也能响应事件
事件阻止
阻止默认行为
javascript
const link = document.getElementById('myLink');
link.addEventListener('click', function(event) {
event.preventDefault(); // 阻止链接跳转
console.log('链接被点击,但不跳转');
});
阻止事件冒泡
javascript
const child = document.getElementById('child');
child.addEventListener('click', function(event) {
event.stopPropagation(); // 阻止事件冒泡
console.log('子元素被点击,事件不会冒泡到父元素');
});
const parent = document.getElementById('parent');
parent.addEventListener('click', function() {
console.log('父元素被点击'); // 点击子元素时不会执行
});
阻止其他事件处理程序
javascript
const button = document.getElementById('myButton');
button.addEventListener('click', function(event) {
console.log('第一个处理程序');
event.stopImmediatePropagation(); // 阻止其他处理程序
});
button.addEventListener('click', function() {
console.log('第二个处理程序'); // 不会执行
});
自定义事件
创建和触发自定义事件:
javascript
// 创建自定义事件
const customEvent = new Event('myCustomEvent', {
bubbles: true, // 是否冒泡
cancelable: true // 是否可取消
});
// 添加自定义事件监听器
const element = document.getElementById('myElement');
element.addEventListener('myCustomEvent', function(event) {
console.log('自定义事件被触发:', event.type);
});
// 触发自定义事件
element.dispatchEvent(customEvent);
// 创建带数据的自定义事件
const customEventWithData = new CustomEvent('myEventWithData', {
detail: { message: '自定义事件数据' }
});
element.addEventListener('myEventWithData', function(event) {
console.log('事件数据:', event.detail.message);
});
element.dispatchEvent(customEventWithData);
学习资源
继续学习:正则表达式
最后更新:2026-02-08