我正在尝试理解JavaScript useCapture
中的addEventListener()
参数。这是我的HTML:
<div id="wrapper">
<button id="button">Click me</button>
</div>
这是我的JavaScript:
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper capture'); }, true);
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper bubble'); }, false);
document.getElementById('button').addEventListener('click', function () { console.log('Button bubble'); }, false);
document.getElementById('button').addEventListener('click', function () { console.log('Button capture'); }, true);
现在,我预计订单为Wrapper capture, Button capture, Button bubble, Button bubble
。令人惊讶的是,这是我的输出:
Wrapper capture
Button bubble
Button capture
Wrapper bubble
两个按钮处理程序正在混淆?我在其他浏览器中测试过,但Chrome,Firefox和IE10都显示相同的行为。我对此感到有点困惑。 The MDN,QuirksMode.org和the spec都清楚地描述了不同阶段以及捕获阶段如何在冒泡阶段之前。为什么我的小实验导致Button bubble
处理程序在Button capture
之前被调用?
这是一个关于正在发生的事情的小提琴:http://jsfiddle.net/Tr7G6/2
//更新 似乎附加处理程序的顺序很重要。
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper capture'); }, true);
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper bubble'); }, false);
document.getElementById('button').addEventListener('click', function () { console.log('Button capture'); }, true);
document.getElementById('button').addEventListener('click', function () { console.log('Button bubble'); }, false);
绑定到第一个捕获和第二个冒泡确实产生了我预期的输出,跨浏览器。但这很愚蠢。为什么这个订单很重要?
答案 0 :(得分:1)
冒泡/捕获仅在事件冒泡/捕获到目标元素时相关,而不是直接在该元素上触发事件时(这是W3C事件模型的“目标阶段”)。在没有“冒泡”或“捕获”的情况下 - click
上的<button>
事件就是这种情况 - 事件将按照添加的顺序进行处理。
例如,如果您要在“包装器”上颠倒侦听器的顺序并单击包装器元素(而不是按钮),您会注意到相同的行为(气泡会先触发):
// 1. "Wrapper Bubble" 2. "Wrapper Capture"
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper bubble'); }, false);
document.getElementById('wrapper').addEventListener('click', function () { console.log('Wrapper capture'); }, true);
但是,如果您使用相同的订单(捕获前的气泡)并单击button
,则捕获将在冒泡前触发。这是因为在button
上触发了“点击”事件,并且在“冒泡”(正常事件流程)之前通过dom“捕获”了该事件。
我已经创建了JSBIN,希望有助于澄清这一点(但是,它可能会增加混乱)。 “ordered”按钮/ div触发第一个片段的顺序,“unordered”按钮和div使用你的第二个顺序。
有关其他信息,请参阅this SO回答和W3C Event Flow文档,特别是Target Phase。