首頁 >web前端 >js教程 >javascript中mouseover、mouseout使用詳解_javascript技巧

javascript中mouseover、mouseout使用詳解_javascript技巧

WBOY
WBOY原創
2016-05-16 15:49:432000瀏覽

本文並沒有像標題說的那樣,真正阻止事件元素的子元素冒泡...

只是在子元素冒泡到事件元素處時進行了一個判斷,判斷是否要觸發事件,哦...不對 應該是是否要運行事件函數中的相關操作...

首先你可以猛戳這裡: 問題的出現​​

 註:jquery中的mouseover/out事件也有此問題

解決方法一:

在ie下有mouseenter 與 mouseleave事件來取代mouseover 和 mouseout。

網路上很多說法,這兩個事件只有ie支持,其他瀏覽器不支援。

但我在最新版本的火狐與谷歌都支援了mouseenter 與 mouseleave! ! ! ! !

另外ie是的支撐範圍是:[ie5 ,所以我們還是別噴ie了...

其他瀏覽器測試了一下:

      在Firefox/3.6.28是不支援mouseenter 與 mouseleave的,Firefox具體從哪個版本開始支援這兩個事件,就不得而知了...

                在Opera9.50 Alpha 與Opera9.00 Beta都不支持。其實Opera現在完全可以不要測試了,最新版的Opera都是webkit核心...

      谷歌低版未測試...

當然這些舊版瀏覽器基本上可以不用管了,所以這應該是最好的解決辦法了:用mouseenter 與 mouseleave事件來取代mouseover 和 mouseout。

此二事件的實例戳這:mouseenter與mouseleave

 註:jquery中也有mouseenter 與 mouseleave事件,相容於所有瀏覽器。

解決方法二:

上面那個方法在舊版的火狐與Google是不支援的,如果你希望得到最大範圍的兼容,那可以繼續往下看

我們利用var reltg = e.relatedTarget ? e.relatedTarget : e.type == 'mouseout' ? e.toElement : e.fromElement 來取得事件相關元素。再透過這個事件相關元素它跟事件元素的關係(包含的關係),來判斷是否要做相關事件處理。

對於mouseout事件來說,reltg就是滑鼠指標離開目標時,滑鼠指標進入的節點。

對於mouseover 事件來說,reltg就是滑鼠指標移到目標節點上時所離開的那個節點。

在li的mouseout的事件函數中,如果reltg為li的子元素我們就不要運行相關操作,如果reltg為li的父元素就運行相關操作。

我們可以透過下面的isMouseLeaveOrEnter函數來判斷li與reltg的包含關係:

//判断事件相关元素与li的关系 如果事件相关元素为li的子元素就返回false 反之返回true
function isMouseLeaveOrEnter(e, handler) { 
  if (e.type != 'mouseout' && e.type != 'mouseover') return false; 
  var reltg = e.relatedTarget ? e.relatedTarget : e.type == 'mouseout' ? e.toElement : e.fromElement;
  while (reltg && reltg != handler) reltg = reltg.parentNode;
  return (reltg != handler);
};

Li.onmouseout = function(e) {
  e = e||window.event;
  if (isMouseLeaveOrEnter(e,this)) {
    //运行相关操作
  };
}

 此方法明顯的缺點就是isMouseLeaveOrEnter中要遍歷所有的父元素了,效能問題

解決方法三:

此方法與方法二其實思路是一樣的,只是我們在這裡透過compareDocumentPosition/contains來判斷li與reltg的包含關係,優化了方法二遍歷所有父元素所帶來的效能問題。

直接看程式碼吧:

//判断node是否为parent的子元素
//if node == parent 也会返回true
function contains(parent, node) {
  if(parent.compareDocumentPosition){ //ff
    var _flag = parent.compareDocumentPosition(node); 
    return (_flag == 20 || _flag == 0)? true : false; 
  }else if(parent.contains){ //ie
    return parent.contains(node);
  }
};

Li.onmouseout = function(e) {
  e = e||window.event;
  var relatedEle = e.relatedTarget ? e.relatedTarget : e.type == 'mouseout' ? e.toElement : e.fromElement
  if (!contains(this, relatedEle)) {
    show.innerHTML=show.innerHTML+'0';
  }

}

compareDocumentPosition() 方法比較兩個節點,並傳回描述它們在文件中位置的整數。

傳回值可能是:

1:沒有關係,兩個節點不屬於同一個文件。

2:第一節點(P1)位於第二個節點後(P2)。

4:第一節點(P1)定位在第二節點(P2)前。

8:第一節點(P1)位於第二節點內(P2)。

16:第二節點(P2)位於第一節點內(P1)。

32:沒有關係,或是兩個節點是同一元素的兩個屬性。

註解:傳回值可以是值的組合。例如,返回 20 意味著在 p2 在 p1 內部(16),並且 p1 在 p2 之前(4)。

而[ie8- 不支援compareDocumentPosition()方法,需要用contains取代compareDocumentPosition()方法那麼強大,它是用來確定 nodeB 是否包含在另一個  nodeA 中:nodeA .contains( nodeB )

以上所述就是本文的全部內容了,希望大家能夠喜歡。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn