【问题标题】:useCapture in addEventListener behaves strangelyaddEventListener 中的 useCapture 行为异常
【发布时间】:2013-08-07 12:28:31
【问题描述】:

我试图理解 JavaScript 的 addEventListener() 中的 useCapture 参数。这是我的 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 MDNQuirksMode.orgthe 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);

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

【问题讨论】:

    标签: javascript dom-events addeventlistener


    【解决方案1】:

    冒泡/捕获仅在事件冒泡/捕获到目标元素时相关,而不是当事件直接在该元素上触发时(这是 W3C 事件模型的“目标阶段”)。如果没有“冒泡”或“捕获”(&lt;button&gt; 上的 click 事件就是这种情况),事件将按照添加的顺序进行处理。

    例如,如果您要颠倒“包装器”上侦听器的顺序并单击包装器 元素(不是按钮),您会注意到相同的行为(气泡会首先触发):

    // 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 触发您的第一个 sn-p 的顺序,而“无序”按钮和 div 使用您第二个的顺序。

    有关更多信息,请参阅this SO 答案和 W3C Event Flow 文档,特别是 Target Phase

    【讨论】:

    • 很好奇他们只是选择忽略传递的任何优先级,只是因为“它无论如何都在同一个元素上”。我在规范中找不到文字文本,但鉴于您的解释和遵循此行为的跨浏览器实现,它一定是真的!谢谢:)
    猜你喜欢
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    相关资源
    最近更新 更多