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

Event listeners registered for capturing phase not triggered before bubbling - why?

本文关键字:为什么 用于 侦听器 事件 注册      更新时间:2023-09-26

我试图了解单击嵌套<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>

根据我所阅读的内容,输出应该是:

outer true
inner true
inner false
outer false

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

outer true
inner false
inner true
outer false

谁能解释这种差异?

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

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

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

鼓泡阶段 事件在由事件目标处理后可由目标的祖先之一处理的过程。有关更多详细信息,请参阅事件流上下文中气泡阶段的说明。

捕获阶段 事件可由以下之一处理的过程 事件目标处理之前的目标的祖先。看 事件流上下文中捕获阶段的说明 更多细节。