原文: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、事件对象:可以获取事件对象的一系列属性,在事件中写一个参数,即可通过参数获取,方法如下:

 wrap.onmouseover = function(e) {
e = window.event || e; // window.event是为了兼容ie下获取事件对象,而e为标准浏览器直接获取
}

  2、事件对象的相关对象
在触发onmouseover及onmouseout时,必定会涉及到其它对象,如:onmouseover的相关对象,即为哪个对象进入的。onmouseout的相关对象即为进入到哪个对象。获取方法如下:

 wrap.onmouseover = function(e) {
e = window.event || e;
var s = e.fromElement || e.relatedTarget; //e.fromElement为IE下onmouseover获取相关对象方法,relatedTarget为标准浏览器下获取方法
}
wrap.onmouseout = function(e) {
e = window.event || e;
var s = e.toElement || e.relatedTarget; //e.toElementIE下onmouseout获取相关对象方法,relatedTarget为标准浏览器下获取方法
}

  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

 <!doctype html>
<html>
<head>
<meta charset="UTF-8">
<style type="text/css">
html,body,div{margin:0;padding:0}
.wrapper {
overflow: hidden;
width: 800px;
background: black;
}
.box {
height: 200px;
background: #FF0;
margin: 80px 0;
}
</style>
</head>
<body>
<div class="wrapper" id="wrap">
<div class="box" id="box"></div>
</div>
</body>
</html>

  既然知道了以上的获取属性及事件的必备方法,那么我们就可以想方法解决问题了
当触发onmouseover时,可能是从对象以外移入的,也有可能是父级移入到子级,以及子级移出到父级,刚才也说过,onmouseover的相关对象是获取从哪个对象进入的。如果是从外面的对象进入的,我们就执行所需的代码。如果是从父级移入到子级或是由子级移出到父级时,则直接跳过。
父级移入到子级对象,相关对象为父级。 子级移出到父级对象,相对对象为子级。
代码如下:

 wrap.onmouseover = function(e) {
e = window.event || e;
var s = e.fromElement || e.relatedTarget;
if (document.all) { //判断浏览器是否为IE,如果存在document.all则为IE
if (!this.contains(s)) { // 判断调用onmouseover的对象(this)是否包含自身或子级,如果包含,则不执行
console.log('IE will over');
}
} else { //标准浏览器下的方法
var reg = this.compareDocumentPosition(s);
if (!(reg == 20 || reg == 0)) {
console.log('Browser will over');
}
}
}

  当触发onmouseout时,可能是从父级移到子级,也可能由子级移到父级,或是移出至父级之外。
父级称到子级,则相关对象为子级,子级称到父级,则相关对象为父级。
代码如下:

 wrap.onmouseout = function(e) {
e = window.event || e;
var s = e.toElement || e.relatedTarget;
if(document.all) {
if (!this.contains(s)) {
console.log('IE will out');
}
} else {
var reg = this.compareDocumentPosition(s);
if (!(reg == 20 || reg == 0)) {
console.log('Browser will out');
}
}
}

问题也就得到了解决。

不过你会发现:onmouseover与onmouseout的判断方法其实是一样的。于是我们得到:
无论是移入还是移出,只要相关对象是父级以外的就可以执行,否则代码不执行。

最后,再为大家提供本人自己写的兼容代码,复制到JS代码后可直接调用。代码如下:

 /*
* 功能:鼠标移入对象触发事件,兼容所有浏览器并防止鼠标在父子对象间移动造成的触发onmouseover的bug
* 参数:第一个参数表示触发的对象,第二个参数表示触发的对象的事件对象,第三个对象表示要执行的函数
* 作者:http://www.cnblogs.com/wuyuchang/
*/
function mouseover(a, e, func) {
e = e || window.event;
var b = e.fromElement || e.relatedTarget; mouseoverAndOut(a, b, func);
}
/*
* 功能:鼠标移出对象触发事件,兼容所有浏览器并防止鼠标在父子对象间移动造成的onmouseout的bug
* 参数:第一个参数表示触发的对象,第二个参数表示触发的对象的事件对象,第三个对象表示要执行的函数
* 作者:http://www.cnblogs.com/wuyuchang/
*/
function mouseout(a ,e, func) {
e = e || window.event;
var b = e.toElement || e.relatedTarget;
mouseoverAndOut(a, b, func);
}
/*
* 功能:鼠标移入或移出对象触发事件,兼容所有浏览器并防止鼠标在父子对象间移动造成的onmouseover & onmouseout的bug
* 参数:第一个参数表示触发的对象,第二个参数表示触发的对象的事件对象,第三个对象表示要执行的函数
* 作者:http://www.cnblogs.com/wuyuchang/
*/
function mouseoverOrOut(a, e, func) {
e = e || window.event;
var b;
if (e.type == 'mouseover') {
b = e.fromElement || e.relatedTarget;
} else if (e.type == 'mouseout') {
b = e.toElement || e.relatedTarget;
}
mouseoverAndOut(a, e, func);
}
/*
* 功能:鼠标移入或移出对象触发事件,兼容所有浏览器并防止鼠标在父子对象间移动造成的onmouseover & onmouseout的bug
* 参数:第一个参数表示触发的对象,第二个参数表示触发的对象的相关对象,第三个对象表示要执行的函数
* 作者:http://www.cnblogs.com/wuyuchang/
*/
function mouseoverAndOut(a, b, func) {
if (document.all) {
if (!(a.contains(b))) {
func();
}
} else {
var res = a.compareDocumentPosition(b);
if(!(res == 20 || res == 0)){
func();
}
}
}

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

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

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

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

    由于HTML中的对象都是层次结构,比如一个Table包含了多个TR,一个TR包含了多个TD Bubble就是一个事件可以从子节点向父节点传递,比如鼠标点击了一个TD,当前的event.srcEleme ...

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

      下图是父元素: 下图是子元素,获取父元素的值,使用props定义属性,这样就可以获取到父元素上传过来的set .place.type,拿到值就可以做一些自己的逻辑处理 二.子元素给父元素传值? 下 ...

  3. js进阶 11-8 jquery如何获取元素相对于父元素的位置

    js进阶 11-8  jquery如何获取元素相对于父元素的位置 一.总结 一句话总结:用jquery的position方法,但是使用这个方法的前提是父元素相对定位,子元素绝对定位,否则和offset ...

  4. JS中如何删除某个父元素下的所有子元素?

    JS中如何删除某个父元素下的所有子元素?这里我介绍几种方法: 1.通过元素的 innerHTML 属性来删除 这种方式我觉得是最有方便的,直接找到你想要的父元素,直接令其 element.innerH ...

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

    方法一: html: <div id="all1"> <div id="left1">1</div> <div id= ...

  6. 子元素z-index高于父元素兄弟元素z-index被遮挡问题

    问题:最近在写样式时,遇到一个这样的问题,子元素的z-index值大于父元素兄弟元素z-index值,结果子元素超出父元素部分被父元素兄弟元素遮挡解决:将父元素的z-index值设置为大于兄弟元素z- ...

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

    例如父窗口定义了一个事件. top: $(dom1).bind('topEvent', function(){}); 那么iframe里面的元素怎样触发父窗口dom1的事件呢?这样吗? $(dom1, ...

  8. 使用flex防止fit-content子元素冲出父元素宽度的方法

    父元素设置了min-width:fit-content后,其宽度由子元素的宽度来决定 <!DOCTYPE html> <html lang="en"> &l ...

  9. ie6下子元素撑大父元素

    今天遇到了一个问题.在给a元素定义hover并且增大尺寸时,IE6下该元素会把父元素撑大,而非IE浏览器则是表现为溢出效果不会撑大父元素(我想要的效果).解决IE6的这个问题是采用了一个定位+负边距的 ...

随机推荐

  1. COM Interop

    1.MSDN上的文章:COM Interop教程 2.接口的三种类型:IDispatch.IUnknown和Dual 3.使用TlbImp来更灵活地自动生成RCW 4.托管事件基于委托,而非托管事件( ...

  2. MEF初体验之六:导出和元素据

    在导出声明这一节中解释了部件导出服务和值的基础知识.在某些情况下,出于多种原因,关联与导出相关的信息是有必要的.通常,它被用来解释一个指定的普通契约实现的能力.这对于允许导入约束满足它的导出,或者导入 ...

  3. Hadoop Java Hdfs API

    1. 在本地文件系统生成一个文本文件,,读入文件,将其第101-120字节的内容写入HDFS成为一个新文件2. 在HDFS中生成文本文件,读入这个文件,将其第101-120字节的内容写入本地文件系统成 ...

  4. 关于继承modelDriven接口action的ajax来电参数

    例如   Model类如下面,Teacher,public class Teacher{  private Integer id. priavte  String name;  private Sch ...

  5. hdu4705 Y 简单树形DP 2013多校训练第十场 J题

    题意:求一棵树中不在一条链中的三个点的对数. 转化一下,用总对数减去在一条链上的三点对数即可. 考虑经过根节点,然后可能是不同的子树中各选一个:或者是子树中选一个,然后当前节点为根的子树以外的节点选一 ...

  6. Java工程(3)——但从谈论用户的角度UI图案

    前言: 海南项目宣告竣工,验收之日,除部分代码有待优化外,亟待改进的就是界面. 米老师说:连你都忍不住去拖下滚动栏,你还指望用户用的舒坦吗? 顿悟: 业务.功能也许是软件的核心,技术也许是软件的精髓. ...

  7. jQuery表格排序总成-tablesorter

    一个.进口单证 <script type="text/javascript" src="js/jquery.js"></script> ...

  8. linux awk命令详细使用方法

    简单介绍 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部 ...

  9. hdu 3068 最长回文(manachar模板)

    Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.回文就是正反读都是一样的字符串,如aba, abba等   Input 输 ...

  10. gcd&&lcm

    1011 最大公约数GCD 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 输入2个正整数A,B,求A与B的最大公约数.   Input 2个数A,B,中 ...