目录
一、事件流说明
1.1 事件流概念
1.2 事件捕获阶段
1.3 事件冒泡阶段
二、事件传播的两个阶段说明
2.1 事件捕获
2.2 事件冒泡
3.3 示例代码
三、阻止冒泡
四、事件解绑
4.1 removeEventListener方法
4.2 使用 DOM0 级事件属性
4.3 使用一次性事件监听器
一、事件流说明
1.1 事件流概念
事件流(Event Flow)是指事件从发生到结束的整个过程。在Web浏览器中,事件流分为两个阶段:事件捕获阶段(Event Capturing Phase)和事件冒泡阶段(Event Bubbling Phase)。
1.2 事件捕获阶段
事件捕获阶段开始于根节点(通常是 document 对象),然后沿着DOM树向下传播到目标节点。在这个阶段,事件会经过所有的父节点,直到到达事件的实际目标(即触发事件的元素)。这意味着,如果你在父元素上注册了一个事件监听器,它会在冒泡到目标元素之前被触发。
1.3 事件冒泡阶段
事件冒泡阶段从事件的目标节点开始,然后向上传播到根节点。在这个阶段,事件会从目标元素开始,逐级向上经过其父元素,直到到达 document 对象。这是事件流的默认行为,也是大多数开发者所熟悉的。
二、事件传播的两个阶段说明
2.1 事件捕获
事件从文档根开始,沿DOM树向下至目标元素。
可以在此阶段设置监听器来拦截事件,阻止事件继续向下传播到目标元素。
在现代浏览器中,可以通过 addEventListener 的第三个参数设置为 true 来启用捕获阶段的监听。
2.2 事件冒泡
事件从目标元素开始,沿DOM树向上至文档根。
这是大多数事件监听器工作的地方,也是默认的事件传播方式。
可以通过 addEventListener 的第三个参数设置为 false (或不设置)来监听冒泡阶段的事件。
3.3 示例代码
// 事件捕获阶段监听
document.getElementById('parent').addEventListener('click', function(event) {
console.log('捕获阶段 - 父元素');
}, true);
// 事件冒泡阶段监听
document.getElementById('child').addEventListener('click', function(event) {
console.log('冒泡阶段 - 子元素');
});
如果 child 元素被点击,事件首先在捕获阶段触发 parent 元素的监听器,然后事件到达 child 元素,并在冒泡阶段触发 child 元素的监听器。如果需要在捕获阶段监听事件,需要在 addEventListener 中将第三个参数设置为 true 。
三、阻止冒泡
当在事件处理函数中调用 event.stopPropagation() ,可以阻止事件继续冒泡到父元素。
const childElement = document.getElementById('child');
childElement.addEventListener('click', function(event) {
event.stopPropagation(); // 阻止事件冒泡
console.log('点击事件在子元素处理,不会传播到父元素');
});
四、事件解绑
事件解绑,即移除事件监听器,可以通过以下几种方法实现:
4.1 removeEventListener方法
const element = document.getElementById('myElement');
const handlerFunction = function(event) {
console.log('事件被触发');
};
// 添加事件监听器
element.addEventListener('click', handlerFunction);
// 移除事件监听器
element.removeEventListener('click', handlerFunction);
注意
- 确保函数引用相同:传递给 addEventListener 和 removeEventListener 的函数引用必须完全相同。
- 捕获与冒泡:如果使用事件捕获添加的监听器,解绑时也需要使用相同的捕获选项。
4.2 使用 DOM0 级事件属性
对于通过直接赋值给事件属性添加的事件监听器(DOM0级事件处理),可以通过将事件属性设置为 null 或一个空函数来“解绑”事件。
const element = document.getElementById('myElement');
// 添加事件监听器(DOM0级)
element.onclick = function(event) {
console.log('点击事件被触发');
};
// “解绑”事件监听器(DOM0级)
element.onclick = null; // 或者 element.onclick = function() {};
4.3 使用一次性事件监听器
通过在 addEventListener 的选项中设置 { once: true } ,可以添加一个只触发一次的事件监听器,该监听器在触发后自动解绑。
const element = document.getElementById('myElement');
// 添加一次性事件监听器
element.addEventListener('click', function(event) {
console.log('点击事件被触发一次');
}, { once: true });
这种监听器在触发一次后自动解绑,无需手动移除。