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("出來了");});