JS子元素oumouseover觸發父元素onmouseout


  JavaScript中,父元素包含子元素:
  當父級設置onmouseover及onmouseout時,鼠標從父級移入子級,則觸發父級的onmouseout后又觸發onmouseover;從子級移入父級后再次觸發父級的oumouseout后又觸發onmouseover。而如果onmouseover內又應用了計時器便會存在較大的問題。下面針對此問題給出解決方案。
  首先,在給出解決方案之前,必須先弄清楚幾個對象及方法,分別如下:
  1、事件對象
  2、事件對象相關屬性(只針對onmouseover及onmouseout),即fromElement、toElement、relatedTarget
  3、判斷一個元素是否包含另一個元素的方法,即element.contains(Node)與element.compareDocumentPosition(Node)

  既然前面已經說了要弄清如上幾個對象及方法,那么,我們就可以分析一下倒底如何去解決這個問題。
分析:
  存在的問題是設置onmouseover時,鼠標從移入父級內時,沒任何問題,但由父級移入子級時,以及由子級稱出到父級時會出現如上問題,那么我們可以想辦法設置當鼠標從父級移入到子級時,或從子級移出到父級時讓觸發對象失效,我們可以通過if語句進行判斷。而事件對象里面有個屬性可以獲取移入移出時的相關對象,下面就來介紹。

  1、事件對象:可以獲取事件對象的一系列屬性,在事件中寫一個參數,即可通過參數獲取,方法如下:

1 wrap.onmouseover = function(e) {
2     e = window.event || e;        // window.event是為了兼容ie下獲取事件對象,而e為標准瀏覽器直接獲取
3 }

  2、事件對象的相關對象
在觸發onmouseover及onmouseout時,必定會涉及到其它對象,如:onmouseover的相關對象,即為哪個對象進入的。onmouseout的相關對象即為進入到哪個對象。獲取方法如下:

1 wrap.onmouseover = function(e) {
2     e = window.event || e;
3     var s = e.fromElement || e.relatedTarget;    //e.fromElement為IE下onmouseover獲取相關對象方法,relatedTarget為標准瀏覽器下獲取方法
4 }
5 wrap.onmouseout = function(e) {
6     e = window.event || e;
7     var s = e.toElement || e.relatedTarget;        //e.toElementIE下onmouseout獲取相關對象方法,relatedTarget為標准瀏覽器下獲取方法
8 }

  3、判斷一個元素是否包含另一個元素
IE下可以使用a.contains(b)判斷a是否包含b
標准瀏覽器下a.compareDocumentPosition(b)有5個值,若為0表示為同一節點,若為2表示a位於b后面,若為4表示a位於b前面,若為10表示a為b的后代,若為20表示a為b的祖級。

  先上個即將用到的示例的HTML及CSS

 1 <!doctype html>
 2 <html>
 3 <head>
 4     <meta charset="UTF-8">
 5     <style type="text/css">
 6     html,body,div{margin:0;padding:0}
 7         .wrapper {
 8             overflow: hidden;
 9             width: 800px;
10             background: black;
11         }
12         .box {
13             height: 200px;
14             background: #FF0;
15             margin: 80px 0;
16         }
17     </style>
18 </head>
19 <body>
20     <div class="wrapper" id="wrap">
21         <div class="box" id="box"></div>
22     </div>
23 </body>
24 </html>

  既然知道了以上的獲取屬性及事件的必備方法,那么我們就可以想方法解決問題了
當觸發onmouseover時,可能是從對象以外移入的,也有可能是父級移入到子級,以及子級移出到父級,剛才也說過,onmouseover的相關對象是獲取從哪個對象進入的。如果是從外面的對象進入的,我們就執行所需的代碼。如果是從父級移入到子級或是由子級移出到父級時,則直接跳過。
父級移入到子級對象,相關對象為父級。 子級移出到父級對象,相對對象為子級。
代碼如下:

 1 wrap.onmouseover = function(e) {
 2     e = window.event || e;
 3     var s = e.fromElement || e.relatedTarget;
 4     if (document.all) {    //判斷瀏覽器是否為IE,如果存在document.all則為IE
 5         if (!this.contains(s)) {    // 判斷調用onmouseover的對象(this)是否包含自身或子級,如果包含,則不執行
 6             console.log('IE will over');
 7         }    
 8     } else {    //標准瀏覽器下的方法
 9         var reg = this.compareDocumentPosition(s);
10         if (!(reg == 20 || reg == 0)) {
11             console.log('Browser will over');
12         }
13     }
14 }

  當觸發onmouseout時,可能是從父級移到子級,也可能由子級移到父級,或是移出至父級之外。
父級稱到子級,則相關對象為子級,子級稱到父級,則相關對象為父級。
代碼如下:

 1 wrap.onmouseout = function(e) {
 2     e = window.event || e;
 3     var s = e.toElement || e.relatedTarget;
 4     if(document.all) {
 5         if (!this.contains(s)) {
 6             console.log('IE will out');
 7         }
 8     } else {
 9         var reg = this.compareDocumentPosition(s);
10         if (!(reg == 20 || reg == 0)) {
11             console.log('Browser will out');
12         }
13     }
14 }

問題也就得到了解決。

不過你會發現:onmouseover與onmouseout的判斷方法其實是一樣的。於是我們得到:
無論是移入還是移出,只要相關對象是父級以外的就可以執行,否則代碼不執行。

最后,再為大家提供本人自己寫的兼容代碼,復制到JS代碼后可直接調用。代碼如下:

 1 /* 
 2  * 功能:鼠標移入對象觸發事件,兼容所有瀏覽器並防止鼠標在父子對象間移動造成的觸發onmouseover的bug
 3  * 參數:第一個參數表示觸發的對象,第二個參數表示觸發的對象的事件對象,第三個對象表示要執行的函數
 4  * 作者:http://www.cnblogs.com/wuyuchang/
 5  */
 6 function mouseover(a, e, func) {
 7     e = e || window.event;
 8     var b = e.fromElement || e.relatedTarget;
 9     
10     mouseoverAndOut(a, b, func);
11 }
12 /* 
13  * 功能:鼠標移出對象觸發事件,兼容所有瀏覽器並防止鼠標在父子對象間移動造成的onmouseout的bug
14  * 參數:第一個參數表示觸發的對象,第二個參數表示觸發的對象的事件對象,第三個對象表示要執行的函數
15  * 作者:http://www.cnblogs.com/wuyuchang/
16  */
17 function mouseout(a ,e, func) {
18     e = e || window.event;
19     var b = e.toElement || e.relatedTarget;
20     mouseoverAndOut(a, b, func);
21 }
22 /* 
23  * 功能:鼠標移入或移出對象觸發事件,兼容所有瀏覽器並防止鼠標在父子對象間移動造成的onmouseover & onmouseout的bug
24  * 參數:第一個參數表示觸發的對象,第二個參數表示觸發的對象的事件對象,第三個對象表示要執行的函數
25  * 作者:http://www.cnblogs.com/wuyuchang/
26  */
27 function mouseoverOrOut(a, e, func) {
28     e = e || window.event;
29     var b;
30     if (e.type == 'mouseover') {
31         b = e.fromElement || e.relatedTarget;
32     } else if (e.type == 'mouseout') {
33         b = e.toElement || e.relatedTarget;
34     }
35     mouseoverAndOut(a, e, func);
36 }
37 /* 
38  * 功能:鼠標移入或移出對象觸發事件,兼容所有瀏覽器並防止鼠標在父子對象間移動造成的onmouseover & onmouseout的bug
39  * 參數:第一個參數表示觸發的對象,第二個參數表示觸發的對象的相關對象,第三個對象表示要執行的函數
40  * 作者:http://www.cnblogs.com/wuyuchang/
41  */
42 function mouseoverAndOut(a, b, func) {
43     if (document.all) {
44         if (!(a.contains(b))) {
45             func();
46         }
47     } else {
48         var res = a.compareDocumentPosition(b);
49         if(!(res == 20 || res == 0)){        
50                 func();
51             }       
52     }           
53 }

(如果是onmouseover,調用mouseover(a, e, func)即可;如果是onmouseout,調用mouseout(a, e, func)即可;或不管onmouseover還是onmouseout直接調用mouseoverOrOut(a, e, func)即可。)


以上為個人經驗之談,如有不到之處還請留言指點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM