捕获后,将执行冒泡但是当我在冒泡阶段打电话给stopPropagation()
时会发生什么?
事件执行流程会改变吗?
var element1 = document.getElementsByClassName('element1')[0],
element2 = document.getElementsByClassName('element2')[0],
element3 = document.getElementsByClassName('element3')[0],
foo = function(e) {
console.log(this.className);
},
stop = function(e) {
console.log('prevent', this.className);
e.preventDefault();
},
stop1 = function(e) {
console.log('stop', this.className);
e.stopPropagation();
};
element1.addEventListener('click', foo); // bubbling
element1.addEventListener('click', foo, true); // caputring
// You cab change handler to "stop"
element2.addEventListener('click', foo);
element2.addEventListener('click', foo, true);
element3.addEventListener('click', stop1);
element3.addEventListener('click', foo, true);
.element1 {
background-color: #b0c4de;
height: 160px;
width: 400px;
cursor: pointer;
}
.element2 {
background-color: pink;
height: 80px;
width: 300px;
position: relative;
top: 20px;
left: 50px;
}
.element3 {
background-color: lightgreen;
height: 30px;
width: 200px;
position: relative;
top: 10px;
left: 50px;
}
<h3>Please open Chrome console and click element3</h3>
<div class="element1">element1
<div class="element2">element2
<div class="element3">element3</div>
</div>
</div>
对于上面的预期输出是
element1
element2
element3
stop element3
输出是
element1
element2
stop element3
element3
stopPropagation
阻止了当前事件的进一步传播。传播意味着如果你从元素转到下一个元素(不是事件监听器上的形式)。在这种情况下,element3
既不在冒泡也不在捕获阶段,而是在目标阶段:
- 捕获阶段:事件对象通过目标的祖先从Window传播到目标的父级。该阶段也称为捕获阶段。
- 目标阶段:事件对象到达事件对象的事件目标。该阶段也称为目标阶段。如果事件类型指示事件未冒泡,则事件对象将在此阶段完成后暂停。
- 泡泡阶段:事件对象以相反的顺序传播通过目标的祖先,从目标的父节点开始,以窗口结束。该阶段也称为起泡阶段。
因此,如果您处于目标阶段,那么事件处理程序是作为冒泡还是作为捕获附加并不重要,因为在从捕获到冒泡的过渡中没有传播到另一个元素。因此,事件处理程序按照它们所附的顺序被忽略,而忽略了阶段标志。
因此,如果你调用stopPropagation
它将阻止传播到下一个元素,但element3
的所有事件监听器无论是否使用useCapture
添加它们都被调用。
像这样在元素3上切换事件监听器的位置
element2.addEventListener('click', foo, true);
element3.addEventListener('click', foo, true);
element3.addEventListener('click', stop1);