JavaScript中mouseover和mouseout多次触发解决办法

news/2024/5/9 13:20:13/文章来源:https://blog.csdn.net/hsd2012/article/details/51644419

问题描述

我希望当鼠标移动到id1上的时候,id2显示,当鼠标离开id1的时候,id2不显示。问题如下:
1.当鼠标从id1上移动到id2上的时候,id由有显示变为不显示,然后变为显示
2.当鼠标从id2上移动到id1上的时候, id2有显示变为不显示,然后变为显示
我希望的是当鼠标在id1或者id2上移动的时候,id2一直显示,不发生变化。

<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代码改为如下,很好解决了问题。

$("#id1").mouseenter(function(){$(this).children().fadeIn(1000);}).mouseleave(function(){$(this).children().fadeOut(1000);});

很多地方都有介绍mouseenter、mouseleave与mouseover、mouseout,于是复制粘贴了一个。
/*********************************************************/
1.mouseover与mouseenter
不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件。
只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件。

2.mouseout与mouseleave
不论鼠标指针离开被选元素还是任何子元素,都会触发 mouseout 事件。
只有在鼠标指针离开被选元素时,才会触发 mouseleave 事件。
/*********************************************************/
现象确实是这个现象,但是过程说的有点模糊,我的理解如下:
当鼠标指针移动到被选元素,会触发 mouseover 事件,这个大家都知道,当鼠标指针由被选元素移动到其子元素,先是触发被选元素的mouseout事件,然后子元素的mouseover事件冒泡到被选元素,此时相当于被选元素先执行了一个mouseout事件,然后执行了一个mouseover事件。
为了验证将代码改为如下

<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函数如下
这里写图片描述
可以简化为如下

//判断两个a中是否包含bfunction 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)返回的信息描述如下:

比特序号意义
0000000元素一致
0000011节点在不同的文档(或者一个在 文档之外)
0000102节点 B 在节点 A 之前
0001004节点 A 在节点 B 之前
0010008节点 B 包含节点 A
01000016节点 A 包含节点 B
10000032浏览器的私有使用

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

获取兼容性性的relatedTarget

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

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效果,所有代码如下。

<!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中是否包含bfunction 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文件中,如下:

(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);

调用的源文件如下:

<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>

经过测试okey。
********备注******
该博文6月5号已发,但是在写另一篇文章的时候,竟然被覆盖了,感觉还是蛮重要的,于是重新写了。

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

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

相关文章

怎样给自己的网站添加一个在浏览器标签、地址栏左边和收藏夹上显示的缩略logo标志

问题描述 不知道&#xff0c;大家有没有注意&#xff0c;有的网站&#xff0c;地址栏上都有一个小图标&#xff0c;如csdn或者是百度。 但是我个人做的网站就没有&#xff0c;怎样添加这样的图标呢&#xff1f; 其实&#xff0c;这个是通过favicon.ico来控制的。 favicon.ico…

当修改网站上的图片等资源时怎样避免客户缓存的问题

问题分析 最近在修改网站上的logo时候&#xff0c;发现修改后&#xff0c;浏览的时候&#xff0c;还是看到之前的图片&#xff0c;PC端多多刷新几次&#xff0c;显示倒是okey&#xff0c;可是手机端依旧是原图片。很明显是缓存的问题&#xff0c;但是我又不想清除手机浏览器缓…

在window中通过IIS发布自己的网站经验总结

转自&#xff1a;https://blog.csdn.net/YSG___/article/details/69061310?utm_mediumdistribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_sourcedistribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.c…

Win10下IIS配置、项目发布、添加网站

转自&#xff1a;https://study-life.blog.csdn.net/article/details/77006831?utm_mediumdistribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.control&depth_1-utm_sourcedistribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2…

内存泄露检查工具及相关网站

Visual Leak Detector http://xiaoruanjian.iteye.com/blog/1091410 灵活自由是C/C语言的一大特色&#xff0c;而这也为C/C程序员出了一个难题。当程序越来越复杂时&#xff0c;内存的管理也会变得越加复杂&#xff0c;稍有不慎就会出现内存问题。内存泄漏是最常见的内存问题之…

源码托管网站推荐——OKSvn

在团队开发时&#xff0c;没使用SVN或者其他版本控制工具必将带来很多不必要的麻烦。在本机搭建SVN的方法虽然可行&#xff0c;但你不能保证你的电脑一直处于运行状态&#xff0c;显然是很不方便的。 我们知道&#xff0c;新浪、谷歌都有项目托管&#xff0c;由于网速…

WordPress 在主题网站添加新年快乐红灯笼特效源码样式

在春节过年的时候看到有在WordPress博客网站添加了红灯笼新年快乐样式。很有过年气氛&#xff0c;今天就给大家分享一下具体的代码样式。 WordPress主题过节灯笼 CSS 样式 这个样式代码可以加在自己的主题 css 样式文件里&#xff0c;也可以单独写进去。部分 WordPress 主题&a…

网站变灰代码,一行代码让网站整体变灰,wordpress网站一行代码全站变灰教程

在遇到特殊情况的时候&#xff0c;我们作为站长需要紧急将网站变灰的需求&#xff0c;在此小编给大家总结了几种方法&#xff0c;通过简单修改一下站点样式即可实现。一段代码让网站整体变灰。这里主要介绍的利用 filter: grayscale属性来实现。供大家学习交流。 网站变灰代码…

WordPress插件 SuperPWA让你的WordPress网站瞬间变成APP

PWA 是 Progressive Web App 的英文缩写&#xff0c; 翻译过来就是渐进式增强 WEB 应用&#xff0c; 是 Google 在 2016 年提出的概念&#xff0c;2017 年落地的 web 技术。目的就是在移动端利用提供的标准化框架&#xff0c;在网页应用中实现和原生应用相近的用户体验的渐进式…

WordPress 网站怎么做会员中心功能【会员中心】

WordPress网站的会员后台与管理员后台默认是一样的&#xff0c;只不过功能少一些而已。但从整体版面上看&#xff0c;Wordpress 网站会员后台并不美观&#xff0c;很多站长并不喜欢这样的后台。那么对于使用 WordPress 建网站的站长&#xff0c;怎么样开发出一个版面美观的会员…

使用angular $interval服务实现购物网站秒杀活动时间倒计时

最近在做一个购物网站的秒杀活动,其中涉及到了一个时间的倒计时. 所谓“秒杀”&#xff0c;就是网络卖家发布一些超低价格的商品&#xff0c;所有买家在同一时间网上抢购的一种销售方式。通俗一点讲就是网络商家为促销等目的组织的网上限时抢购活动。由于商品价格低廉&#xf…

怎么扒站建站_深扒国内建站服务:网站建设哪家服务好?

企业如果想通过互联网来打响品牌&#xff0c;吸引更多客户&#xff0c;一个自己的官方网站是少不了的。如今各种建站服务商也有很多&#xff0c;但是服务质量良莠不齐&#xff0c;这该怎么选择呢&#xff1f;今天就跟大家深扒一下网站建设哪家服务好&#xff0c;让你明白企业到…

python与seo应用_python网络爬虫与SEO搜索引擎优化介绍

1. 什么是爬虫&#xff1f;首先应该弄明白一件事&#xff0c;就是什么是爬虫&#xff0c;为什么要爬虫&#xff0c;博主百度了一下&#xff0c;是这样解释的&#xff1a;网络爬虫(又被称为网页蜘蛛&#xff0c;网络机器人&#xff0c;在FOAF社区中间&#xff0c;更经常的称为网…

PHP网站留言要加验证码,php – 需要一些帮助来添加一些验证码联系表单

嗨,我是PHP的新手,我想要一些帮助.我已经创建了一个联系表单,我想添加一些验证码.我已经创建了一些gif图像,其中包含添加了一些噪音的数字,并将no1命名为code_01.gif,no2等命名为code_02.gif等.我已经将其中的一些设置在我的表单上,静态地用于显示目的,如此&#xff1a;我想添加…

大型网站架构演变和知识体系

之前也有一些介绍大型网站架构演变的文章&#xff0c;例如LiveJournal的、ebay的&#xff0c;都是非常值得参考的&#xff0c;不过感觉他们讲的更多的是每次演变的结果&#xff0c;而没有很详细的讲为什么需要做这样的演变&#xff0c;再加上近来感觉有不少同学都很难明白为什么…

网站安全解决方案

网站安全解决方案1.项目背景根据国家计算机网络应急技术处理协调中心&#xff08;简称CNCERT/CC&#xff09;2008年上半年的统计报告&#xff0c;中国大陆被篡改网站的数量相比往年处于明显上升趋势&#xff0c;共监测到中国大陆被篡改网站总数达到35113 个&#xff0c;同比增加…

借双慧眼识别钓鱼欺诈网站

借双慧眼识别钓鱼欺诈网站 钓鱼欺诈网站&#xff0c;又称仿冒网站。这些网站的内容主要是复制那些正常网站的内容&#xff0c;使得网民粗一看几乎和正常网站一模一样&#xff0c;区别仅限于浏览器的地址。 曾有新闻报道有骗子在北京街头做了个假ATM机&#xff0c;这ATM机和市民…

curl网站开发指南

作者&#xff1a; 阮一峰 日期&#xff1a; 2011年9月 4日 我一向以为&#xff0c;curl只是一个编程用的函数库。 最近才发现&#xff0c;这个命令本身&#xff0c;就是一个无比有用的网站开发工具&#xff0c;请看我整理的它的用法。 curl网站开发指南 阮一峰 整理 curl是一种…

如何修改MOSS网站名(主机标头)

修改MOSS网站名&#xff08;主机标头&#xff09; 编写人&#xff1a;顾劲松 一、问题现状描述 在MOSS中创建的网站时&#xff0c;如果不指定网站的标头&#xff0c;MOSS会使用主机名作为网站标头。例如&#xff0c;我们在服务器myhigerweb上安装部署的MOSS网站&#xff0c;从I…

推荐16个国外的源码下载网站

如今&#xff0c;网上有很多的源代码下载网站&#xff0c;分析和学习别人的代码也是提高自己编程能力的方法之一。今天本文向大家推荐16个国外的代码下载网站。 The Script Library PHP Junkyard Hotscripts Script Dungeon Gscripts CgiScript Perl scripts Java scripts Scri…