4

我试图理解useCaptureJavaScript 中的参数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 都显示相同的行为。我对此有点困惑。MDNQuirksMode.org规范都清楚地描述了不同的阶段以及捕获阶段如何先于冒泡阶段。为什么我的小实验导致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);

绑定到第一个捕获和第二个气泡确实会产生我预期的跨浏览器输出。但这是愚蠢的。为什么这个顺序很重要?

4

1 回答 1

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,希望能帮助澄清这一点(但是,它可能只会增加混乱)。“有序”按钮/ div 触发您的第一个片段的顺序,而“无序”按钮和 div 使用您第二个片段的顺序。

有关其他信息,请参阅SO 答案和 W3C事件流文档,特别是Target Phase

于 2013-08-07T16:15:30.367 回答