onmouseover模拟onmouseenter和mouse类事件理解
说到mouse事件,可能会涉及到很多东西。这里主要谈的是鼠标移入,移出事件。我们知道在js中分别是用onmouseover和onmouseout来表示鼠标移入和移出事件,当然也可以用onmouseenter和onmouseleave来表示鼠标移入和移出。但是这两种移入,移出却有很大的区别。
不得不说,有时候某度出来的问题真的会误导人,各种不负责任的转载,所以还是借鉴居多。下面以函数的形式通俗的来说下着onmouseover,onmouseout ,onmouseenter,onmouseleave的概念:
onmouseover — onmouseout
onmouseover
obj.onmouseover=function(){ |
表示当鼠标移入obj时,触发fn1(),但是当鼠标由元素移到子元素上或者由子元素移动到元素时,都会触发fn1(),这个事件可兼容所有浏览器。
onmouseout
obj.onmouseout=function(){ |
表示当鼠标移出obj时,触发fn2(),但是当鼠标由元素移到子元素上或者由子元素移动到元素时,也都会触发fn2(),与onmouseover一样 ,这个事件也兼容所有浏览器。
onmouseenter — onmouseleave
onmouseenter
obj.onmouseenter=function(){ |
表示当鼠标移入obj时,触发fn1(),并且这个事件不冒泡 ,也就是说鼠标在元素的子元素里移动(包含在子元素和元素之间交叉移动)都不会触发fn1(),在DOM2级并没有定义这个事件,在DOM3级才有定义。IE,FF,Opear都支持这个事件,但是chrome并不支持这个事件。
onmouseleave
obj.onmouseleave=function(){ |
表示当鼠标移出obj时,触发fn2(),并且这个事件不冒泡 ,也就是说鼠标在元素的子元素里移动(包含在子元素和元素之间交叉移动)都不会触发fn2(),在DOM2级并没有定义这个事件,而在DOM3级才有定义。IE,FF,Opear都支持这个事件,但是chrome并不支持这个事件。
实例
这么一个需求,有一个id为box,背景为灰色的div,其有一个id为con,且背景色为白色的子div。如代码,我们需要的是,当鼠标移入box时,隔0.1s后box的背景色变为绿色。鼠标移出box时,box的背景色恢复为灰色。
<style> |

观察上图,我们发现当鼠标在box内移动时,box的背景会不断闪烁变化。这就是onmouseover本来的特性所导致的,在元素与子元素间移动会重复触发fn1()和fn2()。但是文件的title却很正常,如果鼠标在box内,title显示的一直是“移入”。而鼠标在box外,则title显示的一直是“移出”。
jquery方法
在jquery中,这个需求可以用hover函数轻易实现,如:
obj.hover(fn1(),fn2()) ; //具体代码省略 |
由此可知,jquery里的hover=mouseenter+mouseleave,而非hover=mouseover+mouseout,由于jquery良好的封装性,因此mouseenter在chrome中也可以得到很好的支持,但是如何让原生的onmouseenter也支持chrome呢?
由于onmouseover兼容性不错,所以我们想到用onmouseover来模拟onmouseenter。那么如何模拟呢?这里我们可以通过此两者的区别考虑,也就是说无论鼠标在哪里,只要鼠标在box元素里移动(无论是从box元素到con元素,还是从con元素到box元素),都不触发fn1()。同理,只有当鼠标真正离开了box元素(不是从con元素离开到box元素,或者是从box元素离开到con元素),才触发fn2();
可是,又如何知道鼠标是从哪个元素移入到另外一个元素呢?这里,javascript给我们提供了一个relatedTarget 事件属性:
对于onmouseover 事件来说,该属性是鼠标指针移到目标节点上时所离开的那个节点。(IE是fromElement)
对于onmouseout 事件来说,该属性是离开目标时,鼠标指针进入的节点。(IE是toElement)
比如说:鼠标由box元素移入到它的子元素con,则此时,对onmouseover来说,box就是relatedTarget节点。而对onmouseout来说,con就是relatedTarget节点。于是我们对这两个节点判断,在onmouseover时,如果两个节点存在父子关系,则不触发fn1()。而在box内移动时,当发生onmouseout事件,如果两个节点存在父子关系,则不触发fn2();
判断父子关系的函数:
function isSons(obj1,obj2){ |
为了方便起见,我们利用几个标签(id分别为relEle1,relEle2的span元素)来表示鼠标移入,移出元素时relatedTarget的变化。于是就有:
<body id="body"> |
通过代码我们可知,当鼠标在box内部移动时,isSons(this,relEle)总是false(我们可以看到控制台的变化),则永远不会触发fn1()和fn2()。只有当鼠标由外部移入box时,isSons(this,relEle)才为true,此时才会触发fn1(),或者当鼠标由box移出到外部时,才会触发fn2()。效果演示图如下:
