想象一下,我有以下几个要素:
+------------------+
| |
| +----------------+
| | |
| | |
| +----------------+
| |
+------------------+
内部元素具有定位意味着它可以在视觉上坐在其父元素之外,并且我在父元素上放置了一个事件监听器,如下所示:
parent.addEventListener('mouseover', function(e) {
// log mouse is over me
}, false);
如果我直接从底部直接鼠标上方,我会得到一个直接事件,但由于事件路由,如果我从侧面鼠标移过(先击中孩子),我也会收到来自孩子的事件它起泡了。
如果我继续向左走,直到我离开子元素并在父空间中,我将得到一个直接事件,如果我再次向右移动,我将从子元素中获得另一个冒泡事件。 / p>
这是设计,设计绝对正常,但是如果我想在鼠标悬停在我身边时做一个单一的动作(包括我的孩子项目),我需要做一些额外的工作来阻止事件我不是感兴趣...例如,这将起作用:
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);
本质上,代码有一个状态变量来确定鼠标是否已经“超过”父项(通过其子项或不通过子项),如果事件在“过度”时再次触发,则忽略这些事件。我们还捕获了鼠标输出事件并询问它..是相关目标(您即将进入的目标)ME? (父母),还是ME的最终孩子?如果是这样,那么就不要做任何事情......否则将'overed'状态设置为false。
所以代码实际上有效,但想象我不能使用relatedTarget属性来确定下一个目标,你会怎么做这个行为?
我希望这是有道理的,我觉得事件中没有足够的上下文没有relatedTarget但是觉得可能有一个关于改变eventPhase属性的行为的角度(以确定事件是直接的还是冒泡的)。
此外,我不是在寻找答案,说'这不会起作用,即yadda yadda'。我现在正在努力反对w3c事件规范浏览器。
提前致谢, 斯蒂芬。
编辑,只是为了澄清,我希望事件发生,好像我有一个看起来像这样的元素(如果元素实际上是上面的例子):
+------------------+
| |
| +--+
| |
| |
| +--+
| |
+------------------+
答案 0 :(得分:2)
我认为你所追求的是IE的"mouseenter"
事件(当用户将鼠标指针移动到对象的边界内时触发)和"mouseleave"
事件(当用户将鼠标指针移到外面时触发对象的边界):
与
onmouseover
事件不同,onmouseenter
事件不会冒泡。在 换句话说,onmouseenter
事件 当用户移动时不会触发 鼠标指针包含的元素 由对象,而onmouseover
火了。
同样为onmouseleave
。
以下是一个示例:http://jsbin.com/uputi(将/edit
添加到网址以编辑源代码):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Sandbox</title>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<style type="text/css" media="screen">
#outer { width:200px; height:200px; border:1px solid #333; }
#inner { float:right; width:125px; height:80px; margin-right:-80px; border:1px solid #333; }
</style>
<script>
window.onload = function() {
function mouseenter() {
document.getElementById('dbg').innerHTML = 'mouse entered #outer boundary';
}
function mouseleave() {
document.getElementById('dbg').innerHTML = 'mouse left #outer boundary';
}
var outer = document.getElementById('outer');
if ('onmouseenter' in document.body) {
// browser supports mouseenter/mouseleave natively (i.e., IE)
outer.onmouseenter = mouseenter;
outer.onmouseleave = mouseleave;
}
else {
// simulate mouseenter/mouseleave in other browsers
function wrap(fn) {
return function(event) {
var parent = event.relatedTarget;
// Check if we're still within the same parent (traverse up parentNodes)
while (parent && parent != this) {
parent = parent.parentNode
}
if(parent != this) {
// call the *real* mouseover/mouseout handler
fn.call(this, event)
}
}
}
outer.onmouseover = wrap(mouseenter);
outer.onmouseout = wrap(mouseleave);
}
}
</script>
</head>
<body>
<div id="outer">
<div><code>#outer</code></div>
<div> </div>
<div> </div>
<div id="inner"><code>#inner</code></div>
</div>
<div id="dbg"></div>
</body>
</html>
它使用relatedTarget
(在标准浏览器FYI中可以正常工作),但没有状态标志。有关此处显示的仿真的详细信息,请参阅this article。
输入mouseenter
元素以及 #outer
元素时,您只能看到一个#inner
事件被触发。这是你想要的“边界”效应(我认为)。
如果您可以选择在应用程序中包含jQuery,请{j} Query brings these fantastic events to other browsers。 (注意jQuery使用内部概述的技术,稍作修改)。
原型1.6.1 also has these events模拟。
答案 1 :(得分:0)
我认为你只需要stopPropagation