Skip to content

事件处理

1 事件对象 (Event Object)

[补充说明]:当事件发生时,浏览器会创建 event 对象并包含事件详细信息。

javascript
element.addEventListener('click', function(event) {
    // 常用事件属性
    console.log(event.type);          // 事件类型(如 'click')
    console.log(event.currentTarget); // 当前处理事件的元素
    console.log(event.target);        // 实际触发事件的元素
    console.log(event.clientX);       // 鼠标指针X坐标(相对于视口)
    console.log(event.clientY);       // 鼠标指针Y坐标(相对于视口)
    
    // [修正说明]:不同事件类型有特定属性
    if (event instanceof KeyboardEvent) {
        console.log(event.key);       // 键盘按键
    }
    if (event instanceof MouseEvent) {
        console.log(event.button);    // 鼠标按钮
    }
});

2 事件流:冒泡与捕获

[修正术语]:事件流包括三个阶段:捕获 → 目标 → 冒泡

javascript
// 事件冒泡(默认几乎所有事件都会冒泡)
document.getElementById('child').addEventListener('click', function(event) {
    console.log('子元素点击事件');
    event.stopPropagation(); // [修正术语]:停止事件冒泡
});

// 事件捕获(需要在选项中配置)
document.getElementById('parent').addEventListener('click', function(event) {
    console.log('父元素捕获阶段');
}, { capture: true }); // 设置为捕获阶段监听

// 阻止默认行为
document.querySelector('a').addEventListener('click', function(event) {
    event.preventDefault(); // [修正术语]:阻止默认行为
    // 等同于 onclick="return false"
});

FileReader 事件处理

[补充说明]:FileReader 提供异步文件读取功能,包含完整的事件体系。

javascript
const reader = new FileReader();

// 事件监听
reader.onloadstart = function() {
    console.log('开始读取文件');
};

reader.onprogress = function(event) {
    if (event.lengthComputable) {
        const percent = (event.loaded / event.total) * 100;
        console.log(`读取进度: ${percent}%`);
    }
};

reader.onload = function(event) {
    console.log('文件读取完成');
    console.log(reader.result); // 读取结果
};

reader.onerror = function() {
    console.error('读取错误:', reader.error);
};

reader.onabort = function() {
    console.log('用户取消读取');
};

reader.onloadend = function() {
    console.log('读取操作结束(成功或失败)');
};

// 开始读取文件
reader.readAsDataURL(file);

2 事件处理程序绑定方式

DOM0 级事件处理

[补充说明]:传统的HTML属性和DOM属性绑定方式。

html
<!-- HTML属性方式(不推荐) -->
<button onclick="handleClick()">点击我</button>
<!-- 注意:HTML中需要写执行代码,但要注意大小写不敏感 -->

<script>
// DOM属性方式
button.onclick = handleClick; // [修正说明]:不能写 button.onclick = handleClick();

function handleClick() {
    console.log('按钮被点击');
}
</script>

DOM2 级事件处理

[补充说明]:使用 addEventListener 提供更强大的事件处理能力。

javascript
// 标准的事件监听器添加方式
element.addEventListener('click', handler, options);

// options 参数详解
const options = {
    once: true,        // 只执行一次后自动移除
    capture: false,    // 是否在捕获阶段处理
    passive: true      // 表示不会调用 preventDefault()
    // [补充说明]:passive: true 可提升滚动性能
};

// 示例
button.addEventListener('click', function() {
    console.log('按钮点击');
}, { once: true, passive: true });

事件监听器的移除

[补充说明]:移除事件监听器时需要保持相同的引用。

javascript
// 正确的方式:保持函数引用
const handler = function() { console.log('点击') };

// 添加监听器
element.addEventListener('click', handler);

// 移除监听器(需要相同的函数引用)
element.removeEventListener('click', handler);

// 错误示例:匿名函数无法移除
element.addEventListener('click', function() {
    console.log('无法移除的监听器');
});
// element.removeEventListener('click', function() {}); // 无效

事件委托模式

[补充说明]:利用事件冒泡实现高效的事件处理。

javascript
// 在父元素上处理子元素的事件
document.getElementById('list').addEventListener('click', function(event) {
    // 检查实际点击的元素
    if (event.target.tagName === 'LI') {
        console.log('点击了列表项:', event.target.textContent);
    }
});