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://fuckhtml5.blog.163.com/
 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://fuckhtml5.blog.163.com/
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://fuckhtml5.blog.163.com/
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://fuckhtml5.blog.163.com/
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)即可。)

以上为个人经验之谈,如有不到之处还请留言指点。

JS子元素oumouseover触发父元素onmouseout,布布扣,bubuko.com

时间: 2024-08-24 12:14:09

JS子元素oumouseover触发父元素onmouseout的相关文章

javascript阻止子元素冒泡触发父元素的mouseover、mouseout

本文并没有像标题说的那样,真正阻止事件元素的子元素冒泡... 只是在子元素冒泡到事件元素处时进行了一个判断,判断是否要触发事件,哦...不对 应该是是否要运行事件函数中的相关操作... 首先你可以猛戳这里: 问题的出现 注:jquery中的mouseover/out事件也有此问题 解决方法一: 在ie下有mouseenter 与 mouseleave事件来替代mouseover 和 mouseout. 网上很多说法,这两个事件只有ie支持,其他浏览器不支持. 但是我在最新版本的火狐与谷歌都支持了

如何解决鼠标移动到子元素 会触发父元素的mouseout事件

方法一. 用mouseleave/mouseenter代替mouseover/mouseout[最佳方法] mouseover与mouseenter mouseover  => 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件.mouseenter => 只有在鼠标指针从元素外穿入被选元素(到元素内)时,才会触发 mouseenter 事件. mouseout与mouseleave mouseout => 不论鼠标指针离开被选元素还是任何子元素,都会触发 mouse

点击子元素事件不触发父元素事件

<html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <script src="http://cdn.bootcss.com/jquery/2.1.0/jquery.min.js"></script> <style type="text/css">

【转载】设置event.cancelBubble,使触发子元素的onclick不同时触发父元素的onclick

由于HTML中的对象都是层次结构,比如一个Table包含了多个TR,一个TR包含了多个TD Bubble就是一个事件可以从子节点向父节点传递,比如鼠标点击了一个TD,当前的event.srcElement就是这个TD,但是这种冒 泡机制使你可以从TR或者Table处截获这个点击事件,但是如果你event.cancelBubble,则就不能上传事件. 例子: <html> <body> <table border="1" width="26%&qu

二、vue学习--父元素如何获取子元素的值,子元素如何获取父元素的值

下图是父元素: 下图是子元素,获取父元素的值,使用props定义属性,这样就可以获取到父元素上传过来的set .place.type,拿到值就可以做一些自己的逻辑处理 二.子元素给父元素传值? 下图为子元素将值传递出去的方式,使用emit将值公布给父元素,见下图: 父元素需要接受子元素给的值,在父元素中相应的要有propMethods属性,这个属性可以使用v-on的方式绑定,也可以使用@propMethods的方式,见下图: 上图中的login是处理事件,这里点击按钮时需要子元素来触发事件,所以

子div用了float浮动之后,如何撑开父元素,让父元素div自动适应高度的问题

方法一: html: <div id="all1"> <div id="left1">1</div> <div id="left2">1</div> <div style=" clear:both; "></div> </div> css: #left1{ float:left;width:200px;} #left2{ float

jquery:iframe里面的元素怎样触发父窗口元素的事件?

例如父窗口定义了一个事件. top: $(dom1).bind('topEvent', function(){}); 那么iframe里面的元素怎样触发父窗口dom1的事件呢?这样吗? $(dom1, parent.document).trigger('topEvent'); 看似正确,实则误导人. 因为父窗口的jquery对象与iframe里面的jquery对象实际为两个对象(function),iframe里面的jquery并不会触发另一个jquery对象定义的事件.除非你在iframe这样

让一个元素相对于父元素固定定位

之前在项目中,遇到了一个场景,需要实现相对于父元素的fixed定位:在父元素内拖动滚动条时,"fixed"定位的元素不能滑动,在外层拖动滚动条时,父元素及父元素内的所有元素跟着一起滑动.但是position: fixed是相对于窗口进行的定位,不能直接实现我们需要的效果. 我们想让特定子元素相对于父元素"fixed"定位,也就是说,剩余的子元素不定位.那我们可以分开来想,如果添加一个祖先元素assistor,有两个祖先元素,一个用于辅助定位,一个用于包裹不定位的内容

parent([expr]) 取得一个包含着所有匹配元素的唯一父元素的元素集合。

parent([expr]) 概述 取得一个包含着所有匹配元素的唯一父元素的元素集合.大理石构件 你可以使用可选的表达式来筛选. 参数 exprStringV1.0 用来筛选的表达式 示例 描述: 查找每个段落的父元素 HTML 代码: <div><p>Hello</p><p>Hello</p></div> jQuery 代码: $("p").parent() 结果: [ <div><p>H