Heim > Artikel > Web-Frontend > Lösung für das mehrfache Auslösen von Mouseover und Mouseout in JavaScript
Ich hoffe, dass ID2 angezeigt wird, wenn sich die Maus zu ID1 bewegt, und dass ID2 angezeigt wird, wenn die Maus ID1 verlässt. Die Probleme sind wie folgt:
1. Wenn sich die Maus von ID1 zu ID2 bewegt, ändert sich die ID von angezeigt zu nicht angezeigt und dann zu angezeigt.
2 Wenn sich die Maus von ID2 zu ID1 bewegt angezeigt werden, nicht angezeigt werden und dann angezeigt werden
Ich hoffe, dass, wenn sich die Maus über ID1 oder ID2 bewegt, ID2 immer angezeigt wird, ohne sich zu ändern.
<script type="text/javascript" src=" </script><p id="id1" style="width:800px; height:400px; background-color:#F23"> <p id="id2" style="width:400px; height:300px; background-color:#0F8; display:none;"> </p> </p><script type="text/javascript"> $("#id1").mouseover(function(){ $(this).children().fadeIn(1000); }).mouseout(function(){ $(this).children().fadeOut(1000); });</script>
Die anfängliche Problemanalyse, wenn sich die Maus von id1 zu id2 bewegt, weil die Maus von id2 weggeht. Eingabe von id1, a Das Mouseout-Ereignis wird für ID1 ausgelöst, sodass die Anzeige von ID2 nicht angezeigt wird. Wenn sich die Maus dann auf ID2 bewegt, wird aufgrund des Bubbling-Mechanismus das Mouseover auf ID2 angezeigt Das Mouseover-Ereignis auf ID1 wurde ausgelöst und dann wurde ID2 von „nicht angezeigt“ in „angezeigt“ geändert. Auf die gleiche Weise wird ein Mouseout-Ereignis für ID2 ausgelöst, wenn sich die Maus von ID2 zu ID1 bewegt. Oder aufgrund des Blasenmechanismus wird das Mouseout-Ereignis an ID1 übertragen, ID2 wechselt von angezeigt zu nicht angezeigt und dann bewegt sich die Maus Zu id1 wurde zuvor ein Mouseover-Ereignis ausgelöst, und dann wurde id2 von „nicht angezeigt“ in „angezeigt“ geändert.
Es scheint, dass die ultimative Lösung für das oben genannte Problem darin besteht, das Mouseout-Ereignis von id1 zu verhindern, wenn sich die Maus von id1 nach id2 bewegt id1. Dann wird das Problem nicht durch bloßes Verhindern der Blasenbildung gelöst.
Um solche Probleme zu lösen, bietet Jquery die Methoden „Mouseenter“ und „Mouseleave“. Deshalb habe ich den JS-Code wie folgt geändert, wodurch das Problem sehr gut gelöst wurde.
$("#id1").mouseenter(function(){ $(this).children().fadeIn(1000); }).mouseleave(function(){ $(this).children().fadeOut(1000); });
Mouseenter, Mouseleave, Mouseover und Mouseout werden an vielen Stellen eingeführt, daher habe ich eines kopiert und eingefügt.
/**************************************** ***** ************************/
1.Mouseover und MouseEnter
Unabhängig davon, ob der Mauszeiger über das ausgewählte Element oder seine untergeordneten Elemente verläuft, wird das Mouseover-Ereignis ausgelöst.
Das Mouseenter-Ereignis wird nur ausgelöst, wenn der Mauszeiger über das ausgewählte Element verläuft.
2.mouseout und Mouseleave
Das Mouseout-Ereignis wird unabhängig davon ausgelöst, ob der Mauszeiger das ausgewählte Element oder ein untergeordnetes Element verlässt.
Das Mouseleave-Ereignis wird nur ausgelöst, wenn der Mauszeiger das ausgewählte Element verlässt.
/**************************************** ***** *********************/
Das Phänomen ist zwar dieses Phänomen, aber der Prozess ist es Etwas vage. Mein Verständnis ist wie folgt:
Wenn sich der Mauszeiger zum ausgewählten Element bewegt, wird das Mouseover-Ereignis ausgelöst. Wie wir alle wissen, wird das Mouseover-Ereignis ausgelöst, wenn sich der Mauszeiger vom ausgewählten Element zum Unterelement bewegt. Zuerst wird das Mouseout-Ereignis des ausgewählten Elements ausgelöst, und dann wird das Mouseover-Ereignis des Unterelements ausgelöst. Das Ereignis sprudelt bis zum ausgewählten Element, was dem ausgewählten Element entspricht, das zuerst ein Mouseout-Ereignis und dann ein Mouseover ausführt Ereignis.
Um dies zu überprüfen, ändern Sie den Code wie folgt:
<script type="text/javascript" src=" </script><p id="id1" style="width:800px; height:400px; background-color:#F23"> <p id="id2" style="width:400px; height:300px; background-color:#0F8; position:absolute; top:300px;"> </p> </p><script type="text/javascript">$("#id1").mouseover(function(){ //$(this).children().fadeIn(1000); console.log('a'); }).mouseout(function(){ //$(this).children().fadeOut(1000); console.log('b'); });</script>
Bewegen Sie die Maus von der Seite zu id1 und dann von id1 zu id2. Die Konsolenausgabe ist wie unten gezeigt
Sie können es sehen. Die Ereignisse „Mouseover“, „Mouseout“ und „Mouseover“ werden nacheinander aus ID1 aufgerufen, was genau das Gleiche ist wie oben analysiert.
从上面分析,我们可以看出,要实现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中是否包含b function contains(a,b){ return a.contains ? a != b && a.contains(b) :!!(a.compareDocumentPosition(b) & 16); }
这个方法是 DOM Level 3 specification 的一部分,允许你确定 2 个 DOM Node 之间的相互位置。这个方法比 .contains() 强大。这个方法的一个可能应用是排序 DOM Node 成一个详细精确的顺序。NodeA.compareDocumentPosition(NodeB)返回的信息描述如下:
比特 | 序号 | 意义 |
---|---|---|
000000 | 0 | 元素一致 |
000001 | 1 | 节点在不同的文档(或者一个在 文档之外) |
000010 | 2 | 节点 B 在节点 A 之前 |
000100 | 4 | 节点 A 在节点 B 之前 |
001000 | 8 | 节点 B 包含节点 A |
010000 | 16 | 节点 A 包含节点 B |
100000 | 32 | 浏览器的私有使用 |
通过上面我们就可以理解为什么要写成a.compareDocumentPosition(b) & 16因为如果节点 A 包含节点 B,就会返回16,16&16=1,其他的情况结果都会0。
为了兼容各种浏览器,参考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以实现改进mouseenter与mouseleave效果,所有代码如下。
测试,鼠标移动路线如下图路线
由控制台可以很看出,此刻的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);
调用的源文件如下:
<p id="id1" style="width:800px; height:400px; background-color:#F23"> <p id="id2" style="width:400px; height:300px; background-color:#0F8; position:absolute; top:300px;"> </p> </p> <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。
以上就是JavaScript中mouseover和mouseout多次触发解决办法 的内容,更多相关内容请关注PHP中文网(www.php.cn)!