注册捕获阶段的事件监听器在冒泡之前未触发 - 为什么?

cod*_*box 14 javascript javascript-events

我试图理解什么决定了点击嵌套时触发事件处理程序的顺序<div>- 我所看到的似乎与记录的行为不一致所以我正在寻找一些帮助来理解它.

我有2个嵌套的div,每个都有2个事件处理程序,一个用于捕获阶段,另一个用于冒泡阶段:

<html>
    <head>
        <script>
            function setup(){
                var outer = document.getElementById('outer');
                outer.addEventListener('click', function(){console.log('outer false');}, false);
                outer.addEventListener('click', function(){console.log('outer true');}, true);

                var inner = document.getElementById('inner');
                inner.addEventListener('click', function(){console.log('inner false');}, false);
                inner.addEventListener('click', function(){console.log('inner true');}, true);
            }           
        </script>
        <style>
            div {
                border: 1px solid;
                padding: 1em;
            }
        </style>
    </head>
    <body onload="setup()">
        <div id="outer">
            <div id="inner">
                CLICK
            </div>
        </div>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

根据我所读的输出应该是:

outer true
inner true
inner false
outer false
Run Code Online (Sandbox Code Playgroud)

但我实际看到的(在Chrome和Firefox上)是:

outer true
inner false
inner true
outer false
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释这种差异吗?

Ell*_* B. 16

W3C事件流规范(即Chrome和Firefox实现的)是所有事件首先被捕获,直到它们到达目标元素,此时它们再次冒泡.但是,当事件流到达事件目标本身时,事件不再捕获或冒泡 - 它位于目标本身上.由于冒泡/捕获不适用,事件处理程序按照它们的注册顺序触发.尝试交换内部元素事件处理程序的顺序,您会发现它也会更改控制台输出的顺序.

jsFiddle示例:http://jsfiddle.net/RTfwd/1/

最近对DOM事件规范的修订使这一点更加明确(http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html):

冒泡阶段 (bubbling phase)事件目标处理事件,其中一个目标的祖先可以处理事件的过程.有关更多详细信息,请参阅事件流上下文中的气泡阶段说明.

捕获阶段捕获阶段在事件目标处理事件之前,目标的一个祖先可以处理事件的过程.有关更多详细信息,请参阅事件流上下文中的捕获阶段的描述.

  • 向事件目标本身添加事件处理程序时,bubble vs capture不适用.在那个级别,你没有捕捉或冒泡 - 你在目标本身.事件处理程序按照注册顺序触发.更新版本的规范在这一点上更加明确:dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html(Ctrl + F - >冒泡阶段) (5认同)