¿Diferencia entre $ (esto) y event.target?

157

Soy nuevo en jQuery, y estaba haciendo paneles con pestañas, siguiendo el tutorial en JavaScript y jQuery: The Missing Manual , existe esa primera línea cuando el autor hace esto:

   var target = $(this);

Pero traté de hacerlo de esa manera

   var target = evt.target;

y recibí ese error:

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

Y cuando evt.targetvolví a cambiar $(this), funcionó a las mil maravillas.

Quiero saber cuál es la diferencia entre $(this)y evt.target?

Aquí está mi código en caso de que lo necesite:

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
fuente
77
thises una referencia al elemento DOM de JavaScript. $()es el formato proporcionado por jQuery para convertir el elemento DOM en un objeto jQuery. utilizando evt.targetestá haciendo referencia a un elemento, mientras $(this)que está haciendo referencia a un objeto con parámetros a los que tenemos acceso.
Ohgodwhy
2
podría hacer $(evt.target)y (en este caso) terminar con los mismos resultados también. El .attr()método es proporcionado por el objeto jQuery, no por el elemento en sí mismo
BLSully

Respuestas:

294

No es una diferencia entre $(this)y event.target, y uno muy significativo. Si bien this(o event.currentTarget, ver más abajo) siempre se refiere al elemento DOM al que estaba conectado el oyente, event.targetes el elemento DOM real en el que se hizo clic. Recuerde que debido al evento burbujeante, si tiene

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

y adjunte click listener al div externo

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

entonces handlerse invocará cuando haga clic dentro del div externo así como en el interno (a menos que tenga otro código que maneje el evento en el div interno y detenga la propagación).

En este ejemplo, cuando hace clic dentro del div interno, luego en handler:

  • thisse refiere al .outerelemento DOM (porque ese es el objeto al que se adjuntó el controlador)
  • event.currentTargettambién se refiere al .outerelemento (porque ese es el elemento objetivo actual que maneja el evento)
  • event.targetse refiere al .innerelemento (esto le da el elemento donde se originó el evento)

El contenedor jQuery $(this)solo envuelve el elemento DOM en un objeto jQuery para que pueda llamar a las funciones jQuery en él. Puedes hacer lo mismo con $(event.target).

También tenga en cuenta que si vuelve a vincular el contexto de this(por ejemplo, si usa Backbone, se hace automáticamente), apuntará a otra cosa. Siempre puede obtener el elemento DOM real de event.currentTarget.

Petr Bela
fuente
Con este ejemplo, si hace clic en el elemento interno y usa event.currentTarget, ¿obtiene el elemento interno o externo?
merlinpatt
3
currentTargetsiempre es el que tiene el controlador, es decir. el exterior
Petr Bela
Por "en tal caso" se refería a '.inner', no a '.outer', y event.target se refería al elemento interno? Su ejemplo no indicaba en qué se hizo clic, pero quería asegurarme antes de editar. :)
Nils Sens
@NilsSens Sí, significa cuando haces clic en 'interno'. Lo dejaré claro.
Petr Bela
39

thises una referencia para el elemento DOM para el que se maneja el evento (el destino actual). event.targetse refiere al elemento que inició el evento. Eran los mismos en este caso, y a menudo pueden serlo, pero no siempre son necesariamente así.

Puede tener una buena idea de esto al revisar los documentos de eventos de jQuery , pero en resumen:

event.currentTarget

El elemento DOM actual dentro de la fase de burbujeo de eventos.

event.delegateTarget

El elemento donde se adjuntó el controlador de eventos jQuery actualmente llamado.

event.relatedTarget

El otro elemento DOM involucrado en el evento, si lo hay.

event.target

El elemento DOM que inició el evento.

Para obtener la funcionalidad deseada usando jQuery, debe envolverla en un objeto jQuery usando: $(this)o $(evt.target).

El .attr()método solo funciona en un objeto jQuery, no en un elemento DOM. $(evt.target).attr('href')o simplemente evt.target.hrefte dará lo que quieres.

nbrooks
fuente
Son no necesariamente ambas referencias al mismo elemento. Ver la respuesta de Petr.
kralyk
1
Es cierto, gracias por señalar eso. Siempre es interesante releer mis viejas respuestas ...
nbrooks
8

Hay una diferencia significativa en cómo jQuery maneja esta variable con un método "on"

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

Si compara esto con: -

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

http://api.jquery.com/on/ afirma:

Cuando jQuery llama a un controlador, la thispalabra clave es una referencia al elemento donde se entrega el evento ; para eventos directamente vinculados thises el elemento donde se adjuntó el evento y para eventos delegados thises un selector de coincidencia de elementos. (Tenga en cuenta que thispuede no ser igual a event.targetsi el evento ha burbujeado desde un elemento descendiente).

Para crear un objeto jQuery a partir del elemento para que pueda usarse con los métodos jQuery, use $ (this).

Si tenemos

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

Verifique la salida a continuación:

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

Tenga en cuenta que utilizo $para envolver el elemento dom para crear un objeto jQuery, que es como siempre lo hacemos.

Se verá que para el primer caso, this, event.currentTarget, event.targetson todos hace referencia al mismo elemento.

Mientras que en el segundo caso, cuando el delegado de eventos a algún elemento envuelto se activan, event.targetse hace referencia al elemento disparada, mientras que thisy event.currentTargetestán referidos a donde se entrega el evento.

Para thisy event.currentTarget, son exactamente lo mismo de acuerdo con http://api.jquery.com/event.currenttarget/

Jaskey
fuente
3

Hay problemas de navegador cruzado aquí.

Un controlador de eventos típico que no sea jQuery sería algo como esto:

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 normaliza evty hace que el destino esté disponible como thisen los controladores de eventos, por lo que un controlador de eventos típico de jQuery sería algo como esto:

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

Un controlador de eventos híbrido que utiliza jQuery's normalizado evty un objetivo POJS sería algo como esto:

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

Dentro de una función de controlador de eventos o método de objeto, una forma de acceder a las propiedades del "elemento contenedor" es usar la palabra clave especial this. La palabra clave this representa al propietario de la función o método que se está procesando actualmente. Entonces:

  • Para una función global, esto representa la ventana.

  • Para un método de objeto, esto representa la instancia del objeto.

  • Y en un controlador de eventos, esto representa el elemento que recibió el evento.

Por ejemplo:

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

El contenido de las ventanas de alerta después de representar este html respectivamente es:

object Window
object HTMLParagraphElement

Un objeto de evento está asociado con todos los eventos. Tiene propiedades que proporcionan información "sobre el evento", como la ubicación de un clic del mouse en la página web.

Por ejemplo:

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

El contenido de las ventanas de alerta después de representar este html respectivamente es:

object MouseEvent
X = 982 Y = 329
MMKarami
fuente