关于子级mouseover触发影响父级mouseout

第一次写文,大神请绕路,求轻喷~~

先给个简单的布局,先是HTML

<body>
  <div id="outer">
    <div id="inner">
    </div>
  </div>
</body>

然后是CSS

#outer{ width:400px; height:400px; background-color:red; margin:10px auto; position:relative;}
#inner{ width:100px; height:100px; background-color:yellow; position:absolute; left:150px; top:150px;}

这时候页面上看到的布局是这样的

不要在意丑不丑,仅仅意思一下。。

var oOuter = document.getElementById('outer');
var oInner =document.getElementById('inner');
        
oOuter.onmouseover = function(){
    this.style.background = 'blue';
}
        
oOuter.onmouseout = function(){
    this.style.background = 'red';
}

简简单单给外层DIV添加了鼠标移入移出事件,然后我们回到页面尝试一下,发现一点问题也没有,移入时候外层DIV颜色变蓝,移出去变回红色

但是我们如果再加上一句话

oInner.onmouseover = function(e){
    e.stopPropagation();  //或者是alert(1);
}

此时每当我们鼠标移入到黄色DIV的时候,我们发现了外层DIV由蓝色变红了,这是因为鼠标进入子元素的触发了父元素的mouseout事件

之前正常是因为事件冒泡,其实父元素也变色了,不过速度很快人眼没有察觉

此时就要吐槽一下safari了,如果用alert(1)这种阻塞查看的话,父元素还是蓝色!!猜测和浏览器渲染机制有关吧,自己不懂

现在看起来没什么问题,因为反正人眼看不出来

可是如果mouseover和mouseout触发的是定时器导致元素的位置变化啊之类的效果,那么就会有非常不好的用户体验了

那该如何解决?

 

最简单的方法就是使用mouseenter和mouseleave,这两个事件不会因为鼠标从父元素移到子元素就balabala乱来一通,只要你鼠标还在父级里面,怎么跑,也不会触发mouseleave

然后好消息是连IE6都兼容!坏消息是safari不兼容!

这只能手动判断了,下面给出两个方法

aElement.contains(bElement)和aElement.compareDocumentPosition(bElement)

先说contains方法,这个很简单,判断bElement是否在aElement内部

代码如下

oOuter.onmouseout = function(e){if(this.contains(e.relatedTarget)){
        return ;
    }
    
    this.style.background = 'red';
}

注意:有些浏览器(大部分,除了FF之外还支持e.toElement),不过最好用relatedTarget,这个是标准的

然后就会发现问题没有了~

下面说我更喜欢也是更强大的compareDocumentPosition方法,先给出一张图~

何止是只能判断一个元素是否在一个元素之中啊,这完全是判断两个元素文档之间的位置关系啊,非常强大有木有~

高版本浏览器都支持此方法,修改代码如下

oOuter.onmouseout = function(e){
    if(this.compareDocumentPosition(e.relatedTarget) == 20){
        return ;
    }
            
    this.style.background = 'red';
}

注意:contains虽然不够强大,不过兼容IE6,而compareDocumentPosition只能兼容高版本浏览器

 

结语:第一次写好累啊,不过希望坚持下去,多将自己一些经历写出来,是对自己的锻炼,也是算帮助一下起步者。。。(明明自己也是才起步)

posted on 2015-04-05 08:55  __constructor  阅读(1097)  评论(1编辑  收藏  举报

导航