jquery 中有一个hover事件十分的有用,是javascript中的onmouseover和onmouseout无法轻易实现的,没有去看过jquery对 hover事件的实现方法,按我自己的思路来完成这个方法。首先,应该认定jquery的hover方法一定是用onmouseover和 onmouseout方法包装实现的,因为在极简易的情况下,onmouseover和onmouseout和hover是没有区别的例如:
<div id="dd" style="width:100px; height:100px; overflow:hidden; border:1px solid #3d3d3d; position:relative;">
</div>
此时用如下代码:
-
$("#dd").hover(function(){alert("进来了");},function(){alert("出来了");});
2.document.getElementById("dd").onmouseover=function(){alert("进来了");}; document.getElementById("dd").onmouseout=function(){alert("出来了");};
以上两段代码是相同的
但是,如果在dd上添加一个子层dd2的话,情况就不一样了如下:
<div id="dd" style="width:100px; height:100px; overflow:hidden; border:1px solid #3d3d3d; position:relative;">
<div id="dd2" style="width:50px; height:50px; overflow:hidden; background-color:#cccccc; position:absolute; left:30px; top:30px;"></div>
</div>
此时用上面的两段代码,表现出来的效果就差很多了。很多情况下,用jquery的hover方法才是我们想要得到的效果。为什么会造这个差别呢?
最 开始我认为会不会是jquery在写hover方法的时候,写了一个对整个dom进行检查的方法鼠标一直处在dd元素内,即当鼠标滑入dd2 时,jquery会对dd2的父级节点进行遍历来确认dd2是不是dd的子元素。这个理论上是可以实现hover方法的,但是开销太大了,是个不好的方 法,jquery不可能是用这样的方法吧。自己也尝试了一下验证jquery不是用这个方法实现的,验证的方法其实很简单用如下代码:
<div id="dd" style="width:100px; height:100px; border:1px solid #3d3d3d; position:relative;">
<div id="dd2" style="width:50px; height:50px; overflow:hidden; background-color:#cccccc; position:absolute; left:300px; top:300px;"></div>
</div>
js代码如下:
-
$("#dd").hover(function(){alert("进来了");},function(){alert("出来了");});
-
$("#dd2").hover(function(e){e.stopPropagation();});$("#dd").hover(function(){alert("进来了");},function(){alert("出来了");});
运行的结果是代码1,在鼠标滑入滑出dd2时,都会弹出提示;而运行代码2时,滑入滑出dd2都无任何提示。
这表示jquery不是用刚才想的笨方法实现的,同时可以知道的一点是jquery是通过鼠标事件的冒泡完成hover事件的。
返 回到onmouseover和onmouseout来,因为鼠标事件(event)在一个父容器内滑过它的子容器仍然会触发父容器的onmouseout 事件,但是因为事件冒泡的存在,瞬间父容器又会发生成onmouseover事件。这就是说,如果可以延迟onmouseout事件的触发,是可以实现 hover事件的。但是呢,延迟事件是不可能完成的,可以完成的是,对事件函数的延迟处理,只要对onouseout事件函数进行延迟与鼠标有没有回到父 容器的onmouseover事件的判断处理的判断,基本上可以完成hover方法。有了这个思路,马上写出一个hover的代替函数
function bind(elem,ev,callback)
{
if(document.all)
{
elem.attachEvent("on"+ev,callback);
}else{
elem.addEventListener(ev,callback,false);
}
}
function unbind(elem,ev,callback)
{
if(typeof(callback)=="function")
{
if(document.all)
{
elem.detachEvent("on"+ev,callback);
}else{
elem.removeEventListener(ev,callback,false);
}
}else{
if(document.all)
{
elem.detachEvent("on"+ev);
}else{
elem.removeEventListener(ev,false);
}
}
}
function hover(elem,overCallback,outCallback){//实现hover事件
var isHover=false;//判断是否悬浮在上方
var preOvTime=new Date().getTime();//上次悬浮时间
function over(e){
var curOvTime=new Date().getTime();
isHover=true;//处于over状态
if(curOvTime-preOvTime>10)
{//时间间隔超过10毫秒,认为鼠标完成了mouseout事件
overCallback(e,elem);
}
preOvTime=curOvTime;
}
function out(e)
{
var curOvTime=new Date().getTime();
preOvTime=curOvTime;
isHover=false;
setTimeout(function(){
if(!isHover)
{
outCallback(e,elem);
}
},10);
}
bind(elem,"mouseover",over);
bind(elem,"mouseout",out);
};
运行以下代码,正好就是jquery的hover方法
<div id="dd" style="width:100px; height:100px; border:1px solid #3d3d3d; position:relative;">
<div id="dd2" style="width:50px; height:50px; overflow:hidden; background-color:#cccccc; position:absolute; left:30px; top:30px;"></div>
</div>
hover(document.getElementById("dd"),function(){document.getElementById("dd2").innerHTML="进来了";},function(){alert("出来了");});