想象一下,我有以下元素:
+------------------+
| |
| +----------------+
| | |
| | |
| +----------------+
| |
+------------------+
内部元素的定位意味着它可以在视觉上位于其父级之外,我在父级上放置了一个事件侦听器,如下所示:
parent.addEventListener('mouseover', function(e) {
// log mouse is over me
}, false);
如果我从底部直接将鼠标悬停在父级上,我会得到一个直接事件,但是由于事件路由,如果我从侧面鼠标悬停(首先击中子级),我也会收到来自子级的事件,因为它会冒泡.
如果我一直向左走,直到我离开子元素并进入父空间,我将得到一个直接事件,如果我再次向右走,我将从子元素得到另一个冒泡事件。
这是设计使然,设计绝对没问题——如果我想在鼠标悬停在我身上(包括我的子项目)时执行 SINGLE 动作,我需要做一些额外的工作来阻止我不感兴趣的事件。 . 例如,这将起作用:
var isOver = false;
parent.addEventListener('mouseover', function(e) {
if (isOver) return;
isOver = true;
// log mouse is over me
}, false);
parent.addEventListener('mouseout', function(e) {
if (e.relatedTarget == this || e.relatedTarget.isDescendantOf(this)) return;
isOver = false;
// log mouse is leaving me
}, false);
本质上,代码有一个状态变量来确定鼠标是否“超过”父级(通过其子级或不通过其子级),以及事件是否在“超过”时再次触发,这些事件被忽略..我们还捕获鼠标退出事件并问它..是relatedTarget(你要进入的目标)我吗?(父母),还是我最终的孩子?如果是这样,那么不要做任何事情.. 否则将“过度”状态设置为 false。
所以该代码实际上是有效的,但想象一下我不能使用relatedTarget 属性来确定下一个目标,你将如何做这种行为?
我希望这是有道理的,我觉得事件中没有足够的上下文可以在没有 relatedTarget 的情况下执行此操作,但我觉得很可能有一个角度来改变 eventPhase 属性上的行为(以确定事件是直接的还是冒泡的)。
此外,我不是在寻找“这在 IE 中不起作用,yadda yadda”的答案。我现在只针对 w3c 事件规范浏览器工作。
编辑,只是为了澄清,我希望事件发生,就好像我有一个看起来像这样的单个元素(如果元素实际上是上面的例子):
+------------------+
| |
| +--+
| |
| |
| +--+
| |
+------------------+