js onmouseout 与onmouseleave的区别

来源:互联网 发布:淘宝 大类目小类目 编辑:程序博客网 时间:2024/04/30 16:34
 

在IE下解决问题很简单,用onMouseEnter、onMouseLeave来代替onMouseOver、onMouseOut就行了,他们的作用基本相同,前者不会发生冒泡。但是firefox下没有这两个事件,如果用 jQuery的event事件,只要bind mouseleave和mouseenter即可。如果是纯js实现,只能这么做:

通过判断触发onMouseOut事件后鼠标到达的元素是不是包含在父元素(信息栏Div)内,如果是就表示鼠标还在信息栏上,则不隐藏,如果否就表示鼠标真的移出了信息栏,那么信息栏隐藏,思路有了,那么就一步步来解决问题

首先来获取触发onMouseOut事件的元素,IE下event的属性toElement来获得,在firefox下变成了relatedTarget(很是折腾!)
IE:event.toElement    Firefox:event.relatedTarget(注意Firefox下event须要调用函数时传入)

接下来就是判断获取的元素是否是子元素,IE下通过元素的contains(Element)方法可以判断,同样的firefox下没有这个方法!!,不过可以给firefox下的元素定义contains()方法来解决问题,代码如下:

if(typeof(HTMLElement)!="undefined")    //给firefox定义contains()方法,ie下不起作用
{  
      HTMLElement.prototype.contains=function(obj)  
      {  
          while(obj!=null&&typeof(obj.tagName)!="undefind"){ //通过循环对比来判断是不是obj的父元素
       if(obj==this) return true;  
       obj=obj.parentNode;
     }  
          return false;  
      };  
}  

获取和判断搞定后,我们就可以通过判断IE和Firefox来针对处理了,通过navigator.userAgent来判断浏览器:
   if(navigator.userAgent.indexOf("MSIE")>0) {
        return "MSIE";
   }
   if(navigator.userAgent.indexOf("Firefox")>0){
        return "Firefox";
   }


到此为止所有要解决的问题都得到了解决,当触发onMouseOut事件时我们针对不同的浏览器先获取鼠标到达的元素,然后通过判断该元素是否在信息栏(div)内,如果元素是子元素,那么不执行onMouseOut事件,反之则执行事件,隐藏信息栏,完成后的代码如下:
function hideMsgBox(theEvent){ //theEvent用来传入事件,Firefox的方式
        if (theEvent){
               var browser=navigator.userAgent;   //取得浏览器属性
               if (browser.indexOf("Firefox")>0){ //如果是Firefox
                    if (document.getElementById('MsgBox').contains(theEvent.relatedTarget)) { //如果是子元素
                        return;   //结束函式
                        }
                }
                  if (browser.indexOf("MSIE")>0){ //如果是IE
                          if (document.getElementById('MsgBox').contains(event.toElement)) { //如果是子元素
                                return; //结束函式
                           }
                 }
             }
            /*要执行的操作*/
}

在信息栏(Div)上设置onMouseOut=hideMsgBox(event)来调用,解决冒泡问题。
通过设置
window.event.cancelBubble = true (IE) event.stopPropagation() event.preventDefault()
(Firefox)
也可以解决问题,但是需要遍历所有子元素,影响效率,所以还是在触发onMouseOut事件时再进行上述判断分别处理比较合适。

=========================================其他方法=================================================

方案一:

希望实现 当鼠标离开一个DIV的时候触发一个事件处理函数 于是用onmouseout 结果却发现它的触发是不是也太敏感了 原因现在也没有弄清楚 IE下好像是因为区分mouseout时的fromElement还是toElement ,IE 5.5以上的onmouseleave事件就比较好用 偏FF又不支持这个事件 只有自己想办法手工判断了。


<SCRIPT>
/***
* 参数e 是对象传递的触发事件 FF下想访问event对象必须传递event参数
* 参数o 是目标DIV对象
*/   
function fun(e,o) { 
        /* FF 下判断鼠标是否离开DIV */
        if(window.navigator.userAgent.indexOf("Firefox")>=1) { 
            var x = e.clientX + document.body.scrollLeft;
            var y = e.clientY + document.body.scrollTop ;
            var left = o.offsetLeft;
            var top = o.offsetTop;
            var w = o.offsetWidth;
            var h = o.offsetHeight;
            
            if(y < top || y > (h + top) || x > left + w || x<left ) { 
                alert("mouseout");
            }
        }

        /* IE */
        if(o.contains(event.toElement ) == false    ) 
alert("mouseout");
        
    }
</SCRIPT>

<DIV onmouseout=fun(event,this)>content</DIV>


需要注意 在取鼠标的值的时候 一定要加上滚动条已经拖动过的内容e.clientY + document.body.scrollTop 如果只是e.clientY得到是个错误的值 当然如果高宽都很小 是看不出来问题。 取一个对象的高和宽 也可以使用 clientHeight clientWidth 属性 以后遇到FF IE不兼容的时候要多看看FF的开发手册http://developer.mozilla.org/en/docs/DOM:element.offsetLeft

 方案二:(与一相似)

js的onmouseout有很奇怪的一个问题。例如

<div onmouseout="alert(123)">

<a href="#">test</a>

</div>

我们预期只有当鼠标从div中移开的时候才会触发onmouseout事件,可是,事实上,当我们移到div中的元素时,例如本例中的a标签时,就 会触发onmousout事件。也就是说,移到对象的子对象上,也算onmouseout了。这往往会让我们预期的效果达不到。今天的工作就遇到了这个问 题。在blueidea上搜了一下,找了解决办法。兼容IE和FF。

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>test</title>
</head>

<body>
<script type="text/javascript">
function test(obj, e) {
if (e.currentTarget) {
if (e.relatedTarget != obj) {
if (obj != e.relatedTarget.parentNode) {
alert(1);
}
}
} else {
if (e.toElement != obj) {
if (obj != e.toElement.parentNode) {
alert(1);
}
}
}
}
</script>
<div onmouseout="test(this, event)" style="width:100px;height:100px;border:1px #666 solid">
<span style="margin:5px;width:100%;height:100%;border:1px #ff0000 solid">faddsf</span>
</div>
</body>
</html>

今天发现JQ中关于这个问题,已经有了一个好的解决办法了.呵呵,jquery中定义了一种事件叫做"mouseleave",用这个事件做事件句柄的话,就可以解决这个问题了.越来越发现jquery是个好东西了.

方案三:

,jQuery V1.2.2推荐用bind("mouseleave",function(){})来代替以前的mouseover方法
用bind("mouseenter",function(){})来代替mouseout,同样也针对以前的hover方法,要看详细的说明点这个地址:http://docs.jquery.com/Release:jQuery_1.2.2

$(document).ready(function() { 
   $("#a1").bind("mouseleave", function(){
   $('<div style="color:red;">out</div>')
   .insertAfter($(this));
});
});