Różnica między $ (this) a event.target?

157

Jestem nowy w jQuery i robiłem panele z zakładkami, postępując zgodnie z samouczkiem w JavaScript i jQuery: The Missing Manual , jest ta pierwsza linia, gdy autor to robi:

   var target = $(this);

Ale próbowałem to zrobić w ten sposób

   var target = evt.target;

i mam ten błąd:

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

A kiedy evt.targetwróciłem do $(this), działało jak urok.

Chcę wiedzieć, jaka jest różnica między $(this)i evt.target?

Oto mój kod na wypadek, gdybyś go potrzebował:

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
źródło
7
thisjest odniesieniem do elementu JavaScript DOM. $()to format dostarczany przez jQuery do przekształcania elementu DOM w obiekt jQuery. używając evt.targetodwołujesz się do elementu, podczas $(this)gdy odwołujesz się do obiektu z parametrami, do których mamy dostęp.
Ohgodwhy
2
możesz to zrobić $(evt.target)i (w tym przypadku) również skończyć z takimi samymi wynikami. .attr()Sposób jest zapewnione przez obiekt jQuery, a nie samego elementu
BLSully

Odpowiedzi:

294

Jest to różnica między $(this)a event.targeti dość znacząca. Podczas gdy this(lub event.currentTargetpatrz poniżej) zawsze odnosi się do elementu DOM, do którego został dołączony detektor, event.targetjest to rzeczywisty kliknięty element DOM. Pamiętaj, że z powodu bulgotania wydarzeń, jeśli masz

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

i dołącz odbiornik kliknięć do zewnętrznego elementu div

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

wtedy handlerzostanie wywołany po kliknięciu wewnątrz zewnętrznego i wewnętrznego div (chyba że masz inny kod, który obsługuje zdarzenie w wewnętrznym div i zatrzymuje propagację).

W tym przykładzie po kliknięciu wewnątrz wewnętrznego elementu div, a następnie w handler:

  • thisodwołuje się do .outerelementu DOM (ponieważ jest to obiekt, do którego został dołączony program obsługi)
  • event.currentTargetodnosi się również do .outerelementu (ponieważ jest to bieżący element docelowy obsługujący zdarzenie)
  • event.targetodwołuje się do .innerelementu (daje to element, z którego pochodzi zdarzenie)

Opakowanie jQuery opakowuje $(this)element DOM tylko w obiekt jQuery, dzięki czemu można na nim wywoływać funkcje jQuery. Możesz zrobić to samo z $(event.target).

Zauważ również, że jeśli zmienisz kontekst this(np. Jeśli używasz Backbone, zrobisz to automatycznie), wskaże coś innego. Zawsze możesz pobrać rzeczywisty element DOM z event.currentTarget.

Petr Bela
źródło
W tym przykładzie, jeśli klikniesz element wewnętrzny i użyjesz elementu event.currentTarget, czy uzyskasz element wewnętrzny czy zewnętrzny?
merlinpatt
3
currentTargetto zawsze ten z przewodnikiem, tj. zewnętrzny
Petr Bela
Przez „w takim przypadku” miałeś na myśli „.inner”, a nie „.outer” został kliknięty, a event.target odwoływałby się wtedy do elementu wewnętrznego? Twój przykład nie określa, co faktycznie kliknięto, ale chciałem się upewnić przed edycją. :)
Nils Sens
@NilsSens Tak, oznacza to, że klikniesz „wewnętrzny”. Wyjaśnię to.
Petr Bela,
39

thisjest odniesieniem do elementu DOM, dla którego zdarzenie jest obsługiwane (bieżący cel). event.targetodnosi się do elementu, który zainicjował zdarzenie. W tym przypadku były takie same i często mogą, ale niekoniecznie zawsze tak jest.

Możesz to dobrze zrozumieć, przeglądając dokumenty zdarzeń jQuery , ale podsumowując:

event.currentTarget

Bieżący element DOM w fazie propagacji zdarzeń.

event.delegateTarget

Element, do którego została dołączona aktualnie nazywana procedura obsługi zdarzeń jQuery.

event.relatedTarget

Drugi element DOM zaangażowany w zdarzenie, jeśli istnieje.

event.target

Element DOM, który zainicjował zdarzenie.

Aby uzyskać pożądaną funkcjonalność przy użyciu jQuery, należy opakować ją w obiekt jQuery za pomocą: $(this)lub $(evt.target).

Ta .attr()metoda działa tylko na obiekcie jQuery, a nie na elemencie DOM. $(evt.target).attr('href')lub po prostu evt.target.hrefda ci to, czego chcesz.

nbrooks
źródło
Niekoniecznie są to odniesienia do tego samego elementu. Zobacz odpowiedź Petra.
kralyk
1
To prawda, dziękuję za zwrócenie uwagi. Zawsze interesujące jest ponowne przeczytanie moich starych odpowiedzi ...
nbrooks
8

Istnieje znacząca różnica w sposobie, w jaki jQuery obsługuje zmienną this za pomocą metody „on”

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

Jeśli porównasz to z: -

$("outer DOM element").click(function(){
  $(this) // refers to the "outer DOM element"
})
natureshop
źródło
4

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

Gdy jQuery wywołuje procedurę obsługi, thissłowo kluczowe jest odwołaniem do elementu, w którym zdarzenie jest dostarczane ; dla zdarzeń powiązanych bezpośrednio thisto element, do którego zostało dołączone zdarzenie, a dla zdarzeń delegowanych thisjest to selektor pasujący do elementu. (Zauważ, że thismoże to nie być równe, event.targetjeśli zdarzenie zostało przepuszczone przez element podrzędny).

Aby utworzyć obiekt jQuery z elementu, aby można go było używać z metodami jQuery, użyj $ (this).

Jeśli mamy

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

Sprawdź poniższe dane wyjściowe:

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

Zauważ, że używam $do zawijania elementu dom w celu utworzenia obiektu jQuery, co zawsze robimy.

Można by stwierdzić, że w pierwszym przypadku this, event.currentTarget, event.targetsą odwołania do tego samego elementu.

Podczas gdy w drugim przypadku, gdy zostanie wyzwolony delegat zdarzenia do jakiegoś opakowanego elementu, event.targetbędzie odwoływał się do wyzwalanego elementu, podczas gdy thisi event.currentTargetsą odwoływane do miejsca dostarczenia zdarzenia.

Ponieważ thisi event.currentTargetsą dokładnie tym samym, zgodnie z http://api.jquery.com/event.currenttarget/

Jaskey
źródło
3

Występują problemy z różnymi przeglądarkami.

Typowy program obsługi zdarzeń inny niż jQuery wyglądałby tak:

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 normalizuje evti udostępnia element docelowy tak, jak thisw programach obsługi zdarzeń, więc typowa procedura obsługi zdarzeń jQuery wyglądałaby tak:

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

Hybrydowa procedura obsługi zdarzeń, która używa znormalizowanej evtmetody jQuery i celu POJS wyglądałaby tak:

function doSomething(evt) {
    var target = evt.target || evt.srcElement;
    if (target.nodeType == 3) // defeat Safari bug
        target = target.parentNode;
    //do stuff here
}
Burak-Burak
źródło
0

W ramach funkcji obsługi zdarzeń lub metody obiektu jednym ze sposobów uzyskania dostępu do właściwości „elementu zawierającego” jest użycie specjalnego słowa kluczowego this. Słowo kluczowe this reprezentuje właściciela aktualnie przetwarzanej funkcji lub metody. Więc:

  • W przypadku funkcji globalnej reprezentuje okno.

  • W przypadku metody obiektowej reprezentuje instancję obiektu.

  • A w programie obsługi zdarzeń reprezentuje element, który odebrał zdarzenie.

Na przykład:

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

Zawartość okien alertów po wyrenderowaniu tego html to odpowiednio:

object Window
object HTMLParagraphElement

Obiekt Event jest powiązany ze wszystkimi zdarzeniami. Posiada właściwości, które dostarczają informacji „o zdarzeniu”, takie jak lokalizacja kliknięcia myszą na stronie internetowej.

Na przykład:

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

Zawartość okien alertów po wyrenderowaniu tego html to odpowiednio:

object MouseEvent
X = 982 Y = 329
MMKarami
źródło