Maison  >  Article  >  interface Web  >  Solution au déclenchement multiple du survol et de la sortie de la souris en JavaScript

Solution au déclenchement multiple du survol et de la sortie de la souris en JavaScript

黄舟
黄舟original
2017-03-01 14:58:381158parcourir

Description du problème

J'espère que lorsque la souris se déplace vers id1, id2 sera affiché, et lorsque la souris quittera id1, id2 sera affiché. Les problèmes sont les suivants :
1. Lorsque la souris passe de id1 à id2, l'ID passe d'affiché à non affiché, puis à affiché
2. Lorsque la souris passe de id2 à id1, id2 passe de id2 à id2. être affiché à ne pas être affiché, puis à être affiché
Ce que j'espère c'est que lorsque la souris se déplace sur id1 ou id2, id2 sera toujours affiché sans changer.

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

Solution au déclenchement multiple du survol et de la sortie de la souris en JavaScript

Solution du problème

L'analyse initiale du problème, lorsque la souris passe de id1 à id2, car la souris quitte id2 En saisissant id1, un L'événement mouseout est déclenché pour id1, donc l'affichage de id2 devient non affiché. Ensuite, lorsque la souris se déplace vers id2, un événement de survol est déclenché sur id2. En raison du mécanisme de bouillonnement, le survol de la souris sur id2 bouillonne vers id1. L'événement de survol de la souris sur id1 a été déclenché, puis id2 est passé de non affiché à affiché. De la même manière, lorsque la souris passe de id2 à id1, un événement mouseout est déclenché pour id2. Ou en raison du mécanisme de bouillonnement, l'événement mouseout est transmis à id1, id2 passe d'affiché à non affiché, puis la souris se déplace. à id1 Avant, un événement de survol était déclenché, puis id2 est passé de non affiché à affiché.

Il semble que la solution ultime au problème ci-dessus soit d'empêcher l'événement mouseout de id1 lorsque la souris passe de id1 à id2 ; lorsque la souris passe de id2 à id1, empêchez id2 L'événement mouseout bouillonne jusqu'à identifiant1. Dans ce cas, empêcher simplement les bulles ne résoudra pas le problème.

Afin de résoudre ce problème, Jquery fournit les méthodes mouseenter et mouseleave. J'ai donc modifié le code JS comme suit, ce qui a très bien résolu le problème.

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

Mouseenter, mouseleave, mouseover et mouseout sont introduits à de nombreux endroits, j'en ai donc copié et collé un.
/*************************************** ***** ***********************/
1.mouseover et mouseenter
Peu importe que le pointeur de la souris passe par l'élément sélectionné ou que ses éléments enfants déclencheront l'événement de survol.
L'événement mouseenter ne sera déclenché que lorsque le pointeur de la souris passera par l'élément sélectionné.

2.mouseout et mouseleave
L'événement mouseout sera déclenché si le pointeur de la souris quitte l'élément sélectionné ou tout élément enfant.
L'événement mouseleave ne sera déclenché que lorsque le pointeur de la souris quittera l'élément sélectionné.
/*************************************** ***** ********************/
Le phénomène est bien ce phénomène, mais le processus est un peu vague. Ma compréhension est la suivante :
Lorsque le pointeur de la souris se déplace vers l'élément sélectionné, l'événement de survol sera déclenché. Comme nous le savons tous, lorsque le pointeur de la souris se déplace de l'élément sélectionné vers son sous-élément, l'événement mouseout de l'élément sélectionné est d'abord déclenché, puis l'événement mouseover du sous-élément est déclenché. L'événement remonte jusqu'à l'élément sélectionné, ce qui équivaut à ce que l'élément sélectionné exécute d'abord un événement mouseout, puis exécute un mouseover. événement.
Afin de vérifier, modifiez le code comme suit

<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(&#39;a&#39;);
            }).mouseout(function(){
                //$(this).children().fadeOut(1000);
                console.log(&#39;b&#39;);
            });</script>

Déplacez la souris de la page vers id1, puis passez de id1 à id2. La sortie de la console est comme indiqué ci-dessous
. Solution au déclenchement multiple du survol et de la sortie de la souris en JavaScript
Vous pouvez le voir Les événements mouseover, mouseout et mouseover sont appelés successivement à partir de id1, ce qui est exactement le même que celui analysé ci-dessus.

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函数如下  
Solution au déclenchement multiple du survol et de la sortie de la souris en JavaScript
可以简化为如下

//判断两个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)返回的信息描述如下:

比特 序号 意义
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。

获取兼容性性的relatedTarget

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

function getRelated(e){
        var related;
        var type=e.type.toLowerCase();//这里获取事件名字
        if(type==&#39;mouseover&#39;){
            related=e.relatedTarget||e.fromElement
        }else if(type=&#39;mouseout&#39;){
            related=e.relatedTarget||e.toElement
        }        return related; 
    }

改进mouseover和mouseout

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


    
    

测试,鼠标移动路线如下图路线
Solution au déclenchement multiple du survol et de la sortie de la souris en JavaScript
由控制台可以很看出,此刻的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==&#39;mouseover&#39;){
                related=e.relatedTarget||e.fromElement
            }else if(type=&#39;mouseout&#39;){
                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(&#39;id1&#39;);

    $$(id1).over(function(){
        console.log(&#39;mouseover&#39;);
    }).out(function(){
        console.log(&#39;mouseout&#39;);
    }); 
    </script>

经过测试okey。

 以上就是JavaScript中mouseover和mouseout多次触发解决办法 的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn