JS子項目oumouseover觸發父元素onmouseout

來源:互聯網
上載者:User

標籤:style   blog   http   color   java   使用   os   io   

原文: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的bug14  * 參數:第一個參數表示觸發的對象,第二個參數表示觸發的對象的事件對象,第三個對象表示要執行的函數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的bug24  * 參數:第一個參數表示觸發的對象,第二個參數表示觸發的對象的事件對象,第三個對象表示要執行的函數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的bug39  * 參數:第一個參數表示觸發的對象,第二個參數表示觸發的對象的相關對象,第三個對象表示要執行的函數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)即可。)


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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.