每次遇到onmouseover事件的處理就頭疼。比如父標籤A裡面嵌套了兩個子標籤,分別為標籤A1和A2。假設你在父標籤A上綁定了mouseover事件,理想的狀態應該是:當滑鼠從A標籤外移到A標籤上,事件觸發。
但實際情況是,在以下幾種情況下,mouseover事件都會被觸發,為mouseover事件觸發(mouseout事件類別似)。
- 當滑鼠從A標籤外移到A標籤上。
- 當滑鼠從父標籤A移入子標籤B(或C)。
- 當滑鼠從子標籤B移入子標籤C(假設間距足夠小的話)。
之前一直是通過在事件處理函數裡面判斷觸發目前時間的targe是否指定節點來解決上面問題,問題是,當標籤嵌套層次比較多的時候,這個判斷過程就變得很麻煩,還會讓處理函數裡面多處一堆跟邏輯不相關的代碼。
請教了某同事,IE瀏覽器支援mouseenter事件,可以輕鬆搞定以上問題,剛好現在手頭做的東西也是只需要支援IE瀏覽器(\(^o^)/)。然後就想了,如果突然需求變更說要支援其他非IE瀏覽器了,那不就慘了(這也是很有可能發生的),像firefox、chrome都是不支援mouseenter的。那就只能自己試著去類比下了:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>在非IE瀏覽器裡類比mouseenter、mouseleave事件</title>
<style>
.outer{width:400px;height:300px;background:#ccc;}
.inner{float:left;width:150px;height:150px;margin:20px;background:#000;}
</style>
</head>
<body>
<div id="outer" class="outer">
<div id="innerA" class="inner"></div>
<div id="innerB" class="inner"></div>
</div>
<div id="output"></div>
</div>
</body>
<script>
var EventUtil = {
//事件綁定
addEvent:function(element,type,handler){
if(element.attachEvent){ //為IE瀏覽器
element.attachEvent("on"+type,handler);
}else if(element.addEventListener){ //firefox、chrome等瀏覽器
if(type=="mouseenter" || type=="mouseleave"){ //對“mouseenter”、“mouseleave”事件做單獨綁定處理
//利用“mouseover”、“mouseout”來類比“mouseenter”、“mouseenter”
var eType = (type=="mouseenter")?"mouseover":"mouseout";
element.addEventListener(eType,EventUtil.wrapHandler(handler),false);
}else{
element.addEventListener(type,handler,false);
}
}else{ //其他瀏覽器
element["on"+type] = handler;
}
},
//對事件處理函數進行封裝
//如果觸發事件的元素跟綁定事件的元素相同,則調用處理函數
wrapHandler:function(handler){
var func = function(event){
var target = event.target;
var parent = event.relatedTarget;
while(parent && parent!=this){ //
try{parent = parent.parentNode;}
catch(e){break;}
}
//parent不等於this,說明觸發事件的正是綁定事件的element本身
(parent!=this) && (handler.call(target,event));
};
return func;
},
//事件移除,省略
removeEvent:function(element,handler){
//這裡沒有任何東西
}
};
function $(id){return document.getElementById(id);}
EventUtil.addEvent($("outer"),"mouseenter",handler);
EventUtil.addEvent($("outer"),"mouseleave",handler);
//
function handler(e){
var event = null,target = null;
if(window.event){
event = window.event;
target = e.srcElement;
}else{
event = e;
target = e.target;
}
$("output").innerHTML += event.type+":"+target.id+"<br/>";
}
</script>
在firefox和IE 8裡簡單測試了下,順利運行,搞定!
以上只是簡單地在非IE瀏覽器裡類比了mouseenter和mouseleave事件,只是實驗下,代碼寫的有點挫各種見諒,主要的是實現的原理。
文章參考了另一篇博文:http://kb.cnblogs.com/a/1627921/,寫得不錯,就是不知道為什麼下面的“運行代碼”一直沒反應。