Différence entre $ (this) et event.target?

157

Je suis nouveau dans jQuery et je faisais des panneaux à onglets, en suivant le tutoriel en JavaScript et jQuery: The Missing Manual , il y a cette première ligne lorsque l'auteur fait ceci:

   var target = $(this);

Mais j'ai essayé de le faire de cette façon

   var target = evt.target;

et j'ai eu cette erreur:

Uncaught TypeError: Object http://localhost/tabbedPanels/#panel1 has no method 'attr'

Et quand je suis evt.targetrevenu $(this), ça a marché comme un charme.

Je veux savoir quelle est la différence entre $(this)et evt.target?

Voici mon code au cas où vous en auriez besoin:

index.html:

<!DOCTYPE html>
<html>
    <head>
        <title>Tabbed Panel</title>
        <style>
            body {
               width : 100%;
               height: 100%;
            }

            #wrapper {
                margin : auto;
                width : 800px;                
            }

            #tabsContainer {
                overflow: hidden;
            }

            #tabs {                
                padding:0;
                margin:0;
            }                

            #tabs li {
                float : left;
                list-style:none;
            }

            #tabs a {
                text-decoration:none;
                padding : 3px 5px;                
                display : block;                
            }

            #tabs a.active {
                background-color : grey;                
            }            
            #panelsContainer {
                clear: left;
            }            
            #panel1 {
                color : blue;
            }            
            #panel2 {
                color : yellow;
            }
            #panel3 {
                color: green;
            }
            #panel4 {
                color : black;
            }         

        </style>
        <script type="text/javascript" src="jquery-1.8.0.min.js"></script>
        <script type="text/javascript" src="script.js"></script>        
    </head>

    <body>
        <div id="wrapper">
            <div id="tabsContainer">
                <ul id="tabs">
                    <li><a href="#panel1">Panel1</a></li>
                    <li><a href="#panel2">Panel2</a></li>
                    <li><a href="#panel3">Panel3</a></li>
                    <li><a href="#panel4">Panel4</a></li>
                </ul>
            </div>
            <div id="panelsContainer">
                <div id="panel1" class="panel">
                    this is panel1
                </div>
                <div id="panel2" class="panel">
                    this is panel2
                </div>
                <div id="panel3" class="panel">
                    this is panel3
                </div>
                <div id="panel4" class="panel">
                    this is panel4
                </div>                
            </div>
        </div>

    </body>

</html>

script.js:

$(function(){
    $("#tabs a").click(function(evt){
       var target = evt.target,
           targetPanel = target.attr("href");
       $(".panel").hide();
       $("#tabs a.active").removeClass("active");
       target.addClass("active").blur();
       $(targetPanel).fadeIn(300);
       evt.preventDefault();
    });

    $("#tabs a:first").click();
})
Rafael Adel
la source
7
thisest une référence à l'élément JavaScript DOM. $()est le format fourni par jQuery pour transformer l'élément DOM en un objet jQuery. en utilisant evt.targetvous faites référence à un élément, alors qu'avec $(this)vous faites référence à un objet avec des paramètres auxquels nous avons accès.
Ohgodwhy
2
vous pourriez faire $(evt.target)et (dans ce cas) vous retrouver avec les mêmes résultats. La .attr()méthode est fournie par l'objet jQuery, pas par l'élément lui
BLSully

Réponses:

295

Il y a une différence entre $(this)et event.target, et une différence assez significative. Alors que this(ou event.currentTarget, voir ci-dessous) fait toujours référence à l'élément event.targetDOM auquel l'auditeur était attaché, est l'élément DOM réel sur lequel l'utilisateur a cliqué. N'oubliez pas qu'en raison du bouillonnement d'événements, si vous avez

<div class="outer">
  <div class="inner"></div>
</div>

et attachez l'écouteur de clic au div externe

$('.outer').click( handler );

alors le handlersera appelé lorsque vous cliquerez à l'intérieur du div externe ainsi que du div interne (sauf si vous avez un autre code qui gère l'événement sur le div interne et arrête la propagation).

Dans cet exemple, lorsque vous cliquez à l'intérieur du div interne, puis dans le handler:

  • thisfait référence à l' .outerélément DOM (car c'est l'objet auquel le gestionnaire était attaché)
  • event.currentTargetfait également référence à l' .outerélément (car c'est l' élément cible actuel qui gère l'événement)
  • event.targetfait référence à l' .innerélément (cela vous donne l'élément d'où l'événement est né)

L'encapsuleur jQuery enveloppe $(this)uniquement l'élément DOM dans un objet jQuery afin que vous puissiez y appeler des fonctions jQuery. Vous pouvez faire la même chose avec $(event.target).

Notez également que si vous reliez le contexte de this(par exemple, si vous utilisez Backbone, c'est fait automatiquement), il pointera vers autre chose. Vous pouvez toujours obtenir l'élément DOM réel à partir de event.currentTarget.

Petr Bela
la source
Avec cet exemple, si vous cliquez sur l'élément interne et utilisez event.currentTarget, obtenez-vous l'élément interne ou externe?
merlinpatt
3
currentTargetest toujours celui avec le gestionnaire, ie. the external one
Petr Bela
Par "dans ce cas" vous vouliez dire ".inner", pas ".outer" n'a été cliqué, et event.target ferait alors référence à l'élément interne? Votre exemple n'indiquait pas sur quoi on avait cliqué, mais je voulais m'en assurer avant de le modifier. :)
Nils Sens
@NilsSens Oui, cela signifie que vous cliquez sur «intérieur». Je vais clarifier cela.
Petr Bela
39

thisest une référence pour l'élément DOM pour lequel l'événement est géré (la cible actuelle). event.targetfait référence à l'élément qui a déclenché l'événement. Ils étaient les mêmes dans ce cas, et peuvent souvent l'être, mais ils ne le sont pas nécessairement toujours.

Vous pouvez en avoir une bonne idée en consultant la documentation sur les événements jQuery , mais en résumé:

event.currentTarget

L'élément DOM actuel dans la phase de bullage d'événement.

event.delegateTarget

L'élément auquel le gestionnaire d'événements jQuery actuellement appelé était attaché.

event.relatedTarget

L'autre élément DOM impliqué dans l'événement, le cas échéant.

event.target

L'élément DOM qui a déclenché l'événement.

Pour obtenir la fonctionnalité souhaitée à l'aide de jQuery, vous devez l'envelopper dans un objet jQuery en utilisant soit: $(this)ou $(evt.target).

La .attr()méthode ne fonctionne que sur un objet jQuery, pas sur un élément DOM. $(evt.target).attr('href')ou tout simplement evt.target.hrefvous donnera ce que vous voulez.

nbrooks
la source
Ce ne sont pas nécessairement les deux références au même élément. Voir la réponse de Petr.
kralyk
1
C'est vrai, merci de l'avoir signalé. C'est toujours intéressant de relire mes anciennes réponses ...
nbrooks
8

Il y a une différence significative dans la façon dont jQuery gère la variable this avec une méthode "on"

$("outer DOM element").on('click',"inner DOM element",function(){
  $(this) // refers to the "inner DOM element"
})

Si vous comparez cela avec: -

$("outer DOM element").click(function(){
  $(this) // refers to the "outer DOM element"
})
natureshop
la source
4

http://api.jquery.com/on/ déclare:

Lorsque jQuery appelle un gestionnaire, le thismot-clé est une référence à l'élément où l'événement est livré ; pour les événements directement liés thisest l'élément auquel l'événement a été attaché et pour les événements délégués, thisun sélecteur de correspondance d'élément. (Notez que cela thispeut ne pas être égal à event.targetsi l'événement est issu d'un élément descendant.)

Pour créer un objet jQuery à partir de l'élément afin qu'il puisse être utilisé avec les méthodes jQuery, utilisez $ (this).

Si nous avons

<input type="button" class="btn" value ="btn1">
<input type="button" class="btn" value ="btn2">
<input type="button" class="btn" value ="btn3">

<div id="outer">
    <input type="button"  value ="OuterB" id ="OuterB">
    <div id="inner">
        <input type="button" class="btn" value ="InnerB" id ="InnerB">
    </div>
</div>

Vérifiez la sortie ci-dessous:

<script>
    $(function(){
        $(".btn").on("click",function(event){
            console.log($(this));
            console.log($(event.currentTarget));
            console.log($(event.target));
        });


        $("#outer").on("click",function(event){
            console.log($(this));
            console.log($(event.currentTarget));
            console.log($(event.target));
        })
    })
</script>

Notez que j'utilise $pour envelopper l'élément dom afin de créer un objet jQuery, ce que nous faisons toujours.

Vous constaterez que pour le premier cas, this, event.currentTarget, event.targetsont toutes référencées au même élément.

Alors que dans le second cas, lorsque le délégué d'événement à un élément encapsulé est déclenché, il event.targetserait référencé à l'élément déclenché, tandis que thiset event.currentTargetréférencé à l'endroit où l'événement est livré.

Pour thiset event.currentTarget, c'est exactement la même chose selon http://api.jquery.com/event.currenttarget/

Jaskey
la source
3

Il y a des problèmes entre navigateurs ici.

Un gestionnaire d'événements non-jQuery typique serait quelque chose comme ceci:

function doSomething(evt) {
    evt = evt || window.event;
    var target = evt.target || evt.srcElement;
    if (target.nodeType == 3) // defeat Safari bug
        target = target.parentNode;
    //do stuff here
}

jQuery normalise evtet rend la cible disponible comme thisdans les gestionnaires d'événements, donc un gestionnaire d'événements jQuery typique serait quelque chose comme ceci:

function doSomething(evt) {
    var $target = $(this);
    //do stuff here
}

Un gestionnaire d'événements hybride qui utilise jQuery normalisé evtet une cible POJS serait quelque chose comme ceci:

function doSomething(evt) {
    var target = evt.target || evt.srcElement;
    if (target.nodeType == 3) // defeat Safari bug
        target = target.parentNode;
    //do stuff here
}
Betterave-Betterave
la source
0

Dans une fonction de gestionnaire d'événements ou une méthode d'objet, une façon d'accéder aux propriétés de "l'élément contenant" consiste à utiliser le mot clé spécial this. Le mot clé this représente le propriétaire de la fonction ou de la méthode en cours de traitement. Alors:

  • Pour une fonction globale, cela représente la fenêtre.

  • Pour une méthode objet, cela représente l'instance d'objet.

  • Et dans un gestionnaire d'événements, cela représente l'élément qui a reçu l'événement.

Par exemple:

<!DOCTYPE html>
<html>
    <head>
        <script>
        function mouseDown() {
            alert(this);
        }
        </script>
    </head>
    <body>
        <p onmouseup="mouseDown();alert(this);">Hi</p>
    </body>
</html>

Le contenu des fenêtres d'alerte après le rendu de ce html est respectivement:

object Window
object HTMLParagraphElement

Un objet Event est associé à tous les événements. Il possède des propriétés qui fournissent des informations «sur l'événement», telles que l'emplacement d'un clic de souris dans la page Web.

Par exemple:

<!DOCTYPE html>
<html>
    <head>
        <script>
        function mouseDown(event) {
            var theEvent = event ? event : window.event;
            var locString = "X = " + theEvent.screenX + " Y = " + theEvent.screenY;
            alert(event);
                    alert(locString);
        }
        </script>
    </head>
    <body>
        <p onmouseup="mouseDown(event);">Hi</p>
    </body>
</html>

Le contenu des fenêtres d'alerte après le rendu de ce html est respectivement:

object MouseEvent
X = 982 Y = 329
MMKarami
la source