为捕获阶段注册的事件侦听器在冒泡之前未触发 - 为啥?
Posted
技术标签:
【中文标题】为捕获阶段注册的事件侦听器在冒泡之前未触发 - 为啥?【英文标题】:Event listeners registered for capturing phase not triggered before bubbling - why?为捕获阶段注册的事件侦听器在冒泡之前未触发 - 为什么? 【发布时间】:2012-08-04 04:39:51 【问题描述】:我试图了解是什么决定了单击嵌套 <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>
根据what I have read,输出应该是:
outer true
inner true
inner false
outer false
但我实际看到的(在 Chrome 和 Firefox 上)是:
outer true
inner false
inner true
outer false
谁能解释这个差异?
【问题讨论】:
【参考方案1】:W3C 事件流规范(即 Chrome 和 Firefox 实现的内容)是首先捕获所有事件,直到它们到达目标元素,此时它们再次冒泡。但是,当事件流到达事件目标本身时,事件不再捕获或冒泡——它在目标本身上。因为冒泡/捕获不适用,所以事件处理程序按照它们注册的顺序触发。尝试交换内部元素事件处理程序的顺序,您会发现它也会更改控制台输出的顺序。
jsFiddle 示例:http://jsfiddle.net/RTfwd/1/
DOM 事件规范的最新版本更清楚地说明了这一点 (http://dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html):
冒泡阶段 在事件目标处理之后,事件可以由目标的祖先之一处理的过程。有关详细信息,请参阅事件流上下文中对冒泡阶段的描述。
捕获阶段 事件可以由其中之一处理的过程 目标的祖先在被事件目标处理之前。看 在事件流的上下文中对捕获阶段的描述 更多细节。
【讨论】:
所以我的理解是捕获应该在所有元素(包括内部)冒泡之前发生,但这不是我所看到的 - 在内部,冒泡(假)发生在捕获之前(真) 向事件目标本身添加事件处理程序时,冒泡 vs 捕获不适用。在那个层面上,你不是在捕捉或冒泡——你是在目标本身上。事件处理程序按照它们注册的顺序触发。规范的最新版本在这一点上更加清晰:dev.w3.org/2006/webapi/DOM-Level-3-Events/html/DOM3-Events.html(Ctrl+F -> 冒泡阶段) @ElliotB.,那么我们如何在捕获阶段注册它?这甚至可能吗?以上是关于为捕获阶段注册的事件侦听器在冒泡之前未触发 - 为啥?的主要内容,如果未能解决你的问题,请参考以下文章