Aru*_*hny 1376
事件冒泡和捕获是HTML DOM API中事件传播的两种方式,当事件发生在另一个元素内的元素中时,两个元素都已为该事件注册了句柄.事件传播模式确定元素接收事件的顺序.
通过冒泡,事件首先被最内层元素捕获并处理,然后传播到外部元素.
通过捕获,事件首先由最外层元素捕获并传播到内部元素.
捕获也称为"滴流",这有助于记住传播顺序:
涓涓细流,泡沫起来
在过去,Netscape主张事件捕获,而微软则推动事件冒泡.两者都是W3C 文档对象模型事件标准(2000)的一部分.
IE <9 仅使用事件冒泡,而IE9 +和所有主要浏览器都支持这两种情况.另一方面,对于复杂的DOM ,事件冒泡的性能可能略低.
我们可以使用addEventListener(type, listener, useCapture)注册事件处理程序来进行冒泡(默认)或捕获模式.要使用捕获模型,请将第三个参数传递为true.
<div>
<ul>
<li></li>
</ul>
</div>
Run Code Online (Sandbox Code Playgroud)
在上面的结构中,假设li元素中发生了单击事件.
在捕获模型中,事件将由div第一个事件处理(首先点击事件处理程序div),然后ul是目标元素中的最后一个事件处理器li.
在冒泡模型中,会发生相反的情况:事件首先由元素处理li,然后由元素处理ul,最后由div元素处理.
有关更多信息,请参阅
在下面的示例中,如果单击任何突出显示的元素,您可以看到事件传播流的捕获阶段首先发生,然后是冒泡阶段.
var logElement = document.getElementById('log');
function log(msg) {
logElement.innerHTML += ('<p>' + msg + '</p>');
}
function capture() {
log('capture: ' + this.firstChild.nodeValue.trim());
}
function bubble() {
log('bubble: ' + this.firstChild.nodeValue.trim());
}
function clearOutput() {
logElement.innerHTML = "";
}
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', capture, true);
divs[i].addEventListener('click', bubble, false);
}
var clearButton = document.getElementById('clear');
clearButton.addEventListener('click', clearOutput);Run Code Online (Sandbox Code Playgroud)
p {
line-height: 0;
}
div {
display:inline-block;
padding: 5px;
background: #fff;
border: 1px solid #aaa;
cursor: pointer;
}
div:hover {
border: 1px solid #faa;
background: #fdd;
}Run Code Online (Sandbox Code Playgroud)
<div>1
<div>2
<div>3
<div>4
<div>5</div>
</div>
</div>
</div>
</div>
<button id="clear">clear output</button>
<section id="log"></section>Run Code Online (Sandbox Code Playgroud)
Fel*_*ing 499
描述:
quirksmode.org对此有一个很好的描述.简而言之(从quirksmode复制):
事件捕获
使用事件捕获时
Run Code Online (Sandbox Code Playgroud)| | ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 \ / | | | ------------------------- | | Event CAPTURING | -----------------------------------element1的事件处理程序首先触发,element2的事件处理程序最后触发.
事件冒泡
当您使用事件冒泡时
Run Code Online (Sandbox Code Playgroud)/ \ ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 | | | | | ------------------------- | | Event BUBBLING | -----------------------------------element2的事件处理程序首先触发,element1的事件处理程序最后触发.
用什么?
这取决于你想做什么.没有更好的.不同之处在于事件处理程序的执行顺序.大多数情况下,在冒泡阶段发射事件处理程序是可以的,但也可能需要提前解雇它们.
小智 69
如果有两个元素元素1和元素2.元素2在元素1内部,我们附加一个事件处理程序,两个元素让我们说onClick.现在当我们点击元素2时,将执行两个元素的eventHandler.现在问题在于事件将以何种顺序执行.如果首先执行附加了元素1的事件,则称为事件捕获,如果首先执行附加元素2的事件,则称为事件冒泡.根据W3C,事件将在捕获阶段开始,直到它到达目标回到元素然后它开始冒泡
捕获和冒泡状态由addEventListener方法的useCapture参数已知
eventTarget.addEventListener(类型,听众,[方法,useCapture]);
默认情况下,useCapture为false.这意味着它处于冒泡阶段.
var div1 = document.querySelector("#div1");
var div2 = document.querySelector("#div2");
div1.addEventListener("click", function (event) {
alert("you clicked on div 1");
}, true);
div2.addEventListener("click", function (event) {
alert("you clicked on div 2");
}, false);Run Code Online (Sandbox Code Playgroud)
#div1{
background-color:red;
padding: 24px;
}
#div2{
background-color:green;
}Run Code Online (Sandbox Code Playgroud)
<div id="div1">
div 1
<div id="div2">
div 2
</div>
</div>Run Code Online (Sandbox Code Playgroud)
请尝试改变真假.
gm2*_*008 25
我在javascript.info上发现这个教程非常清楚地解释了这个主题.最后的三点总结实际上是在谈论关键点.我在这里引用它:
- 事件首先被捕获到最深的目标,然后冒泡.在IE <9中他们只是泡沫.
- 所有处理程序都在冒泡阶段工作,除了addEventListener,最后一个参数为true,这是在捕获阶段捕获事件的唯一方法.
- 可以通过event.cancelBubble = true(IE)或其他浏览器的event.stopPropagation()来停止冒泡/捕获.
小智 14
DOM 事件描述了事件传播的 3 个阶段: 捕获阶段 \xe2\x80\x93 事件深入到元素。目标阶段 \xe2\x80\x93 事件到达目标元素。冒泡阶段 \xe2\x80\x93 事件从元素中冒泡。
\n\n冒泡
Event propagate to the upto root element is **BUBBLING**.
Run Code Online (Sandbox Code Playgroud)
捕捉
Event propagate from body(root) element to eventTriggered Element is **CAPTURING**.
Run Code Online (Sandbox Code Playgroud)
还有一个Event.eventPhase属性可以告诉您事件是目标事件还是其他地方的事件。
请注意,尚未确定浏览器的兼容性。我已经在Chrome(66.0.3359.181)和Firefox(59.0.3)上对其进行了测试,并且该设备受其支持。
从接受的答案扩展本来就不错的代码段,这是使用eventPhase属性的输出
var logElement = document.getElementById('log');
function log(msg) {
if (logElement.innerHTML == "<p>No logs</p>")
logElement.innerHTML = "";
logElement.innerHTML += ('<p>' + msg + '</p>');
}
function humanizeEvent(eventPhase){
switch(eventPhase){
case 1: //Event.CAPTURING_PHASE
return "Event is being propagated through the target's ancestor objects";
case 2: //Event.AT_TARGET
return "The event has arrived at the event's target";
case 3: //Event.BUBBLING_PHASE
return "The event is propagating back up through the target's ancestors in reverse order";
}
}
function capture(e) {
log('capture: ' + this.firstChild.nodeValue.trim() + "; " +
humanizeEvent(e.eventPhase));
}
function bubble(e) {
log('bubble: ' + this.firstChild.nodeValue.trim() + "; " +
humanizeEvent(e.eventPhase));
}
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', capture, true);
divs[i].addEventListener('click', bubble, false);
}Run Code Online (Sandbox Code Playgroud)
p {
line-height: 0;
}
div {
display:inline-block;
padding: 5px;
background: #fff;
border: 1px solid #aaa;
cursor: pointer;
}
div:hover {
border: 1px solid #faa;
background: #fdd;
}Run Code Online (Sandbox Code Playgroud)
<div>1
<div>2
<div>3
<div>4
<div>5</div>
</div>
</div>
</div>
</div>
<button onclick="document.getElementById('log').innerHTML = '<p>No logs</p>';">Clear logs</button>
<section id="log"></section>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
368545 次 |
| 最近记录: |