JS中mouseover和mouseout多次触发问题如何解决

news/2024/5/10 19:00:58/文章来源:https://blog.csdn.net/mixi9760/article/details/52215199

转载地址:http://www.jb51.net/article/85977.htm


问题描述

我希望当鼠标移动到id1上的时候,id2显示,当鼠标离开id1的时候,id2显示。问题如下:

1.当鼠标从id1上移动到id2上的时候,id由有显示变为不显示,然后变为显示

2.当鼠标从id2上移动到id1上的时候, id2有显示变为不显示,然后变为显示

我希望的是当鼠标在id1或者id2上移动的时候,id2一直显示,不发生变化。

?
1
2
3
4
5
6
7
8
9
10
11
12
<script type= "text/javascript" src= "https://code.jquery.com/jquery-1.12.4.js" ></script>
<div id= "id1" style= "width:800px; height:400px; background-color:#F23" >
<div id= "id2" style= "width:400px; height:300px; background-color:#0F8; display:none;" >
</div>
</div>
<script type= "text/javascript" >
$( "#id1" ).mouseover( function (){
$( this ).children().fadeIn(1000);
}).mouseout( function (){
$( this ).children().fadeOut(1000);
});
</script>

这里写图片描述

问题解决办法

最开始的问题分析,当鼠标从id1上移动到id2上的时候,由于鼠标由id2离开进入id1,针对id1触发了一个mouseout事件,于是id2有显示变为不显示,接着在鼠标移动到id2上,在id2上触发了一个mouseover事件,由于冒泡机制,id2上的mouseover冒泡到id1之前,触发了id1上的mouseover事件,然后id2由不显示变为显示。同理,当鼠标从id2上移动到id1上的时候,针对id2,触发了一个mouseout事件,还是因为冒泡机制,mouseout事件传到id1上,id2由显示变为不显示,接着鼠标移动到id1之前,触发了一个mouseover事件,然后id2有不显示变为显示。

看来,上面的问题归根要解决的是,当鼠标由id1上移动到id2上的时候,阻止id1的mouseout事件;当鼠标从id2上移动到id1上的时候,阻止id2的mouseout事件冒泡到id1之上。那么仅仅通过阻止冒泡是解决不了问题。

为了解决这样的问题,jQuery提供了mouseenter和mouseleave方法。于是将JS代码改为如下,很好解决了问题。

?
1
2
3
4
5
<span style="color:#ff0000;">$("#id1").mouseenter(function(){
$(this).children().fadeIn(1000);
}).mouseleave(function(){
$(this).children().fadeOut(1000);
});</span>


 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件。对应mouseout
只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件。对应mouseleave

这样的话,mouseenter子元素不会反复触发事件,否则在IE中经常有闪烁情况发生。

很多地方都有介绍mouseenter、mouseleave与mouseover、mouseout,于是复制粘贴了一个。

/*********************************************************/

1.mouseover与mouseenter

不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件。

只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件。

2.mouseout与mouseleave

不论鼠标指针离开被选元素还是任何子元素,都会触发 mouseout 事件。
只有在鼠标指针离开被选元素时,才会触发 mouseleave 事件。

/*********************************************************/

现象确实是这个现象,但是过程说的有点模糊,我的理解如下:

当鼠标指针移动到被选元素,会触发 mouseover 事件,这个大家都知道,当鼠标指针由被选元素移动到其子元素,先是触发被选元素的mouseout事件,然后子元素的mouseover事件冒泡到被选元素,此时相当于被选元素先执行了一个mouseout事件,然后执行了一个mouseover事件。

为了验证将代码改为如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script type= "text/javascript" src= "https://code.jquery.com/jquery-1.12.4.js" ></script>
<div id= "id1" style= "width:800px; height:400px; background-color:#F23" >
<div id= "id2" style= "width:400px; height:300px; background-color:#0F8; position:absolute; top:300px;" >
</div>
</div>
<script type= "text/javascript" >
$( "#id1" ).mouseover( function (){
//$(this).children().fadeIn(1000);
console.log( 'a' );
}).mouseout( function (){
//$(this).children().fadeOut(1000);
console.log( 'b' );
});
</script>

鼠标从页面移动到id1,然后由id1移动到id2上,控制台输出如下图

这里写图片描述 

可以看出id1先后调用了mouseover、mouseout、mouseover事件,正好和上面分析的相同。

mouseenter与mouseleave实现分析

原理分析

从上面分析,我们可以看出,要实现mouseenter与mouseleave的效果,就是当鼠标从被选元素移动到其子元素上的时候,被选元素不执行mouseout事件,也不执行子类冒泡过来的mouseover事件,当鼠标从被选元素子元素移动到被选元素上的时候,被选元素不执行mouseover事件,也不执行子类冒泡过来的mouseout事件。

要实现上面的效果,我们需要event对象的一个属性relatedTarget,这个属性就是用来判断 mouseover和mouseout事件目标节点的相关节点的属性。简单的来说就是当触发mouseover事件时,relatedTarget属性代表的就是鼠标刚刚离开的那个节点,当触发mouseout事件时它代表的是鼠标移向的那个对象。由于MSIE不支持这个属性,不过它有代替的属性,分别是 fromElement和toElement。除此,我们还需要contains方法,来判断一个对象是否包含在另外一个对象中。

这样当鼠标移动,需要判断以下两条即可

1.调用mouseover,只需要判断relatedTarget是否被选元素的子元素,如果是,则不执行(当于从被选元素子元素移动到被选元素,不执行mouseover;当于从被选元素移动到被选元素子元素,不执行冒泡过来的mouseover);

2.调用mouseout,只需要判断relatedTarget是否被选元素的子元素,如果是,则不执行(当于从被选元素子元素移动到被选元素,不执行子元素冒泡过来的mouseout;当于从被选元素移动到被选元素子元素,不执行mouseover);

实现过程

判断两个元素是否存在包含关系

jquery中封装了contains函数如下

这里写图片描述 

可以简化为如下

?
1
2
3
4
//判断两个a中是否包含b
function contains(a,b){
return a.contains ? a != b && a.contains(b) :!!(a.compareDocumentPosition(b) & 16);
}

compareDocumentPosition介绍

这个方法是 DOM Level 3 specification 的一部分,允许你确定 2 个 DOM Node 之间的相互位置。这个方法比 .contains() 强大。这个方法的一个可能应用是排序 DOM Node 成一个详细精确的顺序。NodeA.compareDocumentPosition(NodeB)返回的信息描述如下:

比特 序号 意义

通过上面我们就可以理解为什么要写成a.compareDocumentPosition(b) & 16因为如果节点 A 包含节点 B,就会返回16,16&16=1,其他的情况结果都会0。

获取兼容性性的relatedTarget

为了兼容各种浏览器,参考jquery源码,写出如下代码,来获取mouseover和mouseout事件目标节点的相关节点的属性relatedTarget。

?
1
2
3
4
5
6
7
8
9
10
function getRelated(e){
var related;
var type=e.type.toLowerCase(); //这里获取事件名字
if (type== 'mouseover' ){
related=e.relatedTarget||e.fromElement
} else if (type= 'mouseout' ){
related=e.relatedTarget||e.toElement
}
return related; 
}

改进mouseover和mouseout

改进mouseover和mouseout以实现改进mouseenter与mouseleave效果,所有代码如下。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id= "id1" style= "width:800px; height:400px; background-color:#F23" >
<div id= "id2" style= "width:400px; height:300px; background-color:#0F8; position:absolute; top:300px;" >
</div>
</div>
<script type= "text/javascript" src= "https://code.jquery.com/jquery-1.12.4.js" ></script>
<script type= "text/javascript" >
//判断两个a中是否包含b
function contains(a,b){
return a.contains ? a != b && a.contains(b) :!!(a.compareDocumentPosition(b) & 16);
}
function getRelated(e){
var related;
var type=e.type.toLowerCase(); //这里获取事件名字
if (type== 'mouseover' ){
related=e.relatedTarget||e.fromElement
} else if (type= 'mouseout' ){
related=e.relatedTarget||e.toElement
}
return related; 
}
$( function (){
$( "#id1" ).mouseover( function (e){
//判断鼠标从哪移到id1上面
var related=getRelated(e); 
//如果related是id1的子元素id2,即从子元素id2移动到id1,或是related为id1,即从id1移动到其子元素id2上面,则不进行任何操作,否则进行相应的操作
if ( this !=related && !contains( this ,related)){
console.log( 'mouseover' );
}
}).mouseout( function (e){
//判断鼠标要从id1上面移动到哪去?
var related=getRelated(e); 
//如果related是id1,即当id1从其子元素移动到id1上,或是related是id2,即从id1上移动到其子元素,不进行任何操作,否则进行相应的操作
if ( this !=related && !contains( this ,related)){
console.log( 'mouseout' );
}
});
});
</script>
</body>
</html>

测试,鼠标移动路线如下图路线

由控制台可以很看出,此刻的mouseover和mouseout已经完全具备mouseenter与mouseleave效果效果。

这里写图片描述 

代码的封装

如果每次进行这样的操作,都需要加载Jquery或是写很多代表,将是件繁琐的事,为了便于以后操作,进行了适当的封装,模拟Jquery,生成自己的mouseenter与mouseleave。代码封装到dqMouse.js文件中,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
( function (w){
var dqMouse = function (obj) {
// 函数体
return new dqMouse.fn.init(obj);
}
dqMouse.fn = dqMouse.prototype = {
// 扩展原型对象
obj: null ,
dqMouse: "1.0.0" ,
init: function (obj) {
this .obj=obj;
return this ;
},
contains: function (a,b) {
return a.contains ? a != b && a.contains(b) :!!(a.compareDocumentPosition(b) & 16);
},
getRelated: function (e) {
var related;
var type=e.type.toLowerCase(); //这里获取事件名字
if (type== 'mouseover' ){
related=e.relatedTarget||e.fromElement
} else if (type= 'mouseout' ){
related=e.relatedTarget||e.toElement
}
return related; 
},
over: function (fn){
var obj= this .obj;
var _self= this ;
obj.onmouseover= function (e){ 
var related=_self.getRelated(e); 
if ( this !=related && !_self.contains( this ,related)){
fn();
}
}
return _self;
},
out: function (fn){
var obj= this .obj;
var _self= this ;
obj.onmouseout= function (e){
var related=_self.getRelated(e); 
if (obj!=related && !_self.contains(obj,related)){
fn();
}
}
return _self;
}
dqMouse.fn.init.prototype = dqMouse.fn;
window.dqMouse = window.$$= dqMouse;
})(window);

调用的源文件如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<div id= "id1" style= "width:800px; height:400px; background-color:#F23" >
<div id= "id2" style= "width:400px; height:300px; background-color:#0F8; position:absolute; top:300px;" >
</div>
</div>
<script type= "text/javascript" src= "dqMouse.js" ></script>
<script type= "text/javascript" >
var id1=document.getElementById( 'id1' );
$$(id1).over( function (){
console.log( 'mouseover' );
}).out( function (){
console.log( 'mouseout' );
}); 
</script>

以上所述是小编给大家介绍的JS中mouseover和mouseout多次触发问题如何解决的相关内容,希望对大家有所帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_900216.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP家教系统源码 请家教网站源码 自适应手机端

下载&#xff1a;https://download.csdn.net/download/qq_45102995/87774656 源码采用thinkphpmysql主流框架开发&#xff0c;前端采用bootstrap框架 自适应手机端 源码是很老的了&#xff0c;要用PHP5.4才可以&#xff0c;搭建流程很简单&#xff0c;老手2分钟基本就能搭建完…

CSS样式里使用JavaScript(onmouseover/onmouseout)

<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > < HTML > < HEAD > < TITLE > CSS样式里使用JavaScript(onmouseover/onmouseout)2 </ TITLE > < META NAME "Generator" CONTENT "EditPlus&qu…

[asp.net]利用HttpRequest登录到某个网站,然后获取网站信息

问题&#xff1a;有的网站的相关内容必须要在登录后才可以查看&#xff0c;其登录信息保存在session变量之中。这样&#xff0c;使用asphttp等组件就难以正确得到所要的信息。 解决&#xff1a;使用asp.net中的httprequest和httpresponse来实现。 要点&#xff1a; 1。 通过附加…

3个CSS动画库,比Animated还好用,让你的网站酷炫起来

本文首发于https://www.1024nav.com/tools/css-animation-library 转载请注明出处 整理了日常前端开发中常用的css动画库&#xff0c;让你的网页动起来&#xff0c;可以在生成中使用&#xff0c;非常酷炫&#xff0c;值得收藏 animxyz AnimXYZ 可帮助您为网站创建、自定义和…

2022年前端面试必备网站【1024nav】它来了~

整理了大半年的前端面经&#xff0c;终于上线了&#xff5e;&#xff5e;欢迎收藏&#xff0c;关注&#xff0c;转发。 1024nav是什么? 1024nav是一个前端开发者必备的学习网站&#xff0c;网站的内容都是精心编写的原创内容。 为什么做这个网站呢&#xff1f; 主要是现在很…

让网站变成灰白色(网站去色)

在html标签添加filter属性 html {filter: grayscale(100%);}添加的效果如下&#xff1a; 去除效果

使用Tale搭建个人博客网站(基于java)

前言&#xff08;背景&#xff09;&#xff1a; 最近几天笔者在搭建一个博客网站。由于作者有自己的服务器&#xff0c;本着不浪费资源的态度&#xff0c;于是就在其上部署个博客网站。虽然使用学生优惠申请的服务器&#xff08;最低配&#xff09;&#xff0c;但用来更新下自己…

腾讯云Ubuntu安装JDK、tomcat、mysql、部署网站步骤详解

腾讯云Ubuntu配置部署步骤&#xff1a;安装JDK、Tomcat&#xff0c;mysql。部署一个Web的项目演示 1.购买服务器&#xff1a;这个不用我说了&#xff0c;学生党可以直接用自己的优惠一元购机 2.Xshell和Xftp或者winscp 因为是远程操作服务器&#xff0c;用一个命令操作页面最好…

程序员必备精粹网站汇总

文章目录 &#xff11;、超好用的搜索引擎(1)秘迹搜索(2)快搜&#xff0d;快人一步(3) DogeDoge搜索(4)GitLogs(5)小白盘 2、学习网站(1)ACM编程学习网站(2)面试刷题学习网站(3)基础语言学习 3、ppt4、图片操作(1) 图片无限变大(2) waifu2x无损放大图片(3) Remove Image Backgr…

前端笔记—从入门到坟墓[网站基础与优化][12.1]

网站icon图标 引入方式&#xff1a; <link rel"shortcut icon" href"favicon.ico" type"image/x-icon">ico图片制作方式&#xff1a; 1&#xff0c;准备一张400*400的图片。 2&#xff0c;登陆http://www.bitbug.net/网站进行图片格式转…

25 个精美的手机网站模板

现如今&#xff0c;iPhone 横行&#xff0c;Android 满天飞&#xff0c;WP7 蓄势待发的势态下&#xff0c;网站没有个手机版都好像很 out 一般。 于是本文向你推荐 25 个制作精美的手机网站模板&#xff0c;提供模板下载以及在线演示&#xff0c;你值得拥有。 Dossier Mobi Sti…

网站内容结构化探讨[1]

无意间浏览到一个承接网页制作的公司的网站——唐宋中国。   首先网站的设计给我一个很好的印象&#xff0c;因此特意留意了一下它的源代码&#xff08;做页面的职业病&#xff09;&#xff0c;结果发现了一些问题&#xff0c;而这些问题&#xff0c;可能正好是学习web标准的…

网站内容结构化探讨[2]--主导航的问题

结构化确实是个让人头疼的工作。为了追求一个好的结构&#xff08;或者说比较好的&#xff09;&#xff0c;往往需要花费掉很多时间&#xff0c;这在追求效率的今天&#xff0c;也许是不被老板允许的。所以很多网站虽然看上去抛弃了表格布局&#xff0c;而其实质上&#xff0c;…

知识产权相关网站2021.7更新

#知识产权相关网站 网站一&#xff1a;WIPO[Directory of Intellectual Property Offices] https://www.wipo.int/directory/en/urls.jsp 网站二&#xff1a;国家知识产权 - 公共服务网 http://ggfw.cnipa.gov.cn:8010/PatentCMS_Center/ 网站地图-IPR http://ipr.mofco…

厚积薄发2021最新个人站长建站模版发布震惊【qipinfuwu.com.V1.0】

厚积薄发2021最新个人站长建站程序发布震惊【qipinfuwu.com.V1.0】实例可直接运行 1.0文件清单 建站程序及文件 1-主页模块.bat 代码 echo off for /f %%i in (‘dir /ad /b’) do copy zhuye.html %%i for /f %%i in (‘dir /ad /b’) do copy 4-页面清单.bat %%i for …

Java、JSP校园信息交流发布网站设计与实现

技术&#xff1a;Java、JSP等 摘要&#xff1a;在高新技术发展的今天&#xff0c;因特网的高速发展给人们带来了极大的便利&#xff0c;使人们的生活变得更加的丰富多彩&#xff0c;人们在生活中通过网络交流获得更多的信息。特别是年轻的大学生群体中更是对周围的信息交流有着…

Java、JSP校友录管理网站的设计与实现

技术&#xff1a;Java、JSP等 摘要&#xff1a;随着B/S模式越来越受到人们的接受&#xff0c;各种在浏览器中给我们带来的服务应运而生&#xff0c;更多的用户花费更多的时间在这些系统中&#xff0c;在随着潮流的同时&#xff0c;我便想利用这次毕业设计的时间来做一个对广大学…

利用QQ通讯组件实现网站立刻联系客服以及一键加群的功能【C#winform实现】

创建一个windows窗体&#xff0c;添加 .cs代码&#xff1a; private void simpleButton1_Click(object sender, EventArgs e){Process.Start("CHROME.EXE", "http://wpa.qq.com/msgrd?v3&uin联系人的qq号&siteqq&menuyes");/*<a target&qu…

两款 Js 插件为你的网站添彩

在网页中合理的利用一些特效能带给人眼前一亮的感觉。今天给大家分享两款很有意思的 Js 特效插件。 输入框打字冒光特效 这款特效本博客也在使用&#xff0c;也有很多人问过是怎么实现的。具体的效果请看 GIF 图&#xff1a; 食用方法&#xff1a; 普通网站&#xff1a; 在网站…

从ST网站下载STM32标准库的流程

打开搜索器&#xff0c;搜索ST官方网站&#xff0c;打开。 如果英文不是很好&#xff0c;点击更换中文。 找到STM32微控制软件&#xff0c;点击打开。 找到标准外设软件库 点击我们想要的系列&#xff0c;示例以F4为基准。 点击获取软件。 点击下载 STM32F4