2012-02-02 6 views
20

Próbuję dowiedzieć się, jak powiązać zdarzenie z dynamicznie tworzonymi elementami. Potrzebuję tego wydarzenia, aby utrzymać się na żywiole nawet po jego zniszczeniu i regeneracji.Implementacja "żywego" spinacza jQuery z natywną wersją Javascript

Oczywiście z funkcją na żywo jQuery jest łatwa, ale co by wyglądało jak zaimplementowana z natywną wersją Javascript?

+1

Zawsze można przeczytać źródło jQuery: s. Nie jestem jednak pewny, jak daleko by to wyglądało od natywnego JS, ponieważ jestem pewny, że będzie on w znacznym stopniu zależał od tego punktu (pod względem używania selektorów i czegokolwiek). – Corbin

+0

Tylko jedna uwaga: '.live()' jest przestarzałe przez długi, długi czas. Został zastąpiony przez '.delegate()', który został zastąpiony przez '.on()', więc użyj ostatniego. Co więcej, ostatni pokazuje różnicę między wiązaniem a delegowaniem, więc możesz rzucić okiem. Najważniejsze jest sprawdzenie celu zdarzenia. – Tadeck

+0

Ta moja odpowiedź może pomóc http://stackoverflow.com/a/27373951/1385441 –

Odpowiedz

21

Oto prosty przykład:

function live(eventType, elementId, cb) { 
    document.addEventListener(eventType, function (event) { 
     if (event.target.id === elementId) { 
      cb.call(event.target, event); 
     } 
    }); 
} 

live("click", "test", function (event) { 
    alert(this.id); 
}); 

Podstawowym założeniem jest to, że chcesz dołączyć obsługi zdarzeń do dokumentu i niech się bańkę zdarzeń DOM. Następnie sprawdź właściwość event.target, aby sprawdzić, czy pasuje ona do żądanych kryteriów (w tym przypadku tylko element id).

Edit:

@shabunc odkrył dość duży problem z moim solution-- wydarzeń na elementy podrzędne nie zostaną wykryte poprawnie. Jednym ze sposobów, aby to naprawić jest spojrzenie na elementy przodków aby sprawdzić, czy mają określony id:

function live (eventType, elementId, cb) { 
    document.addEventListener(eventType, function (event) { 
     var el = event.target 
      , found; 

     while (el && !(found = el.id === elementId)) { 
      el = el.parentElement; 
     } 

     if (found) { 
      cb.call(el, event); 
     } 
    }); 
} 
+0

Do dokumentu lub - bardziej efektywnie - do pojemnika poza którym nie spodziewasz się elementów, które Cię interesują. – Tadeck

+0

To jest słuchanie każdego zdarzenia kliknięcia, a gdy pojawia się zdarzenie kliknięcia, sprawdza, czy identyfikator celu pasuje do podanego identyfikatora i wykonuje funkcję zwrotną. Dość interesujące :) – InspiredJW

+0

Dobrze. I jak podkreśla @Tadeck, możesz ograniczyć bulgotanie do innego elementu zawierającego bardziej efektywny słuchacz. –

14

Oprócz postu Andrzeja i komentarzu Benjamin jest, być może jest to opcja:

Dzięki temu można użyj "nav .item a" jako selektora. Na podstawie kodu Andrew.

function live (eventType, elementQuerySelector, cb) { 
    document.addEventListener(eventType, function (event) { 

     var qs = document.querySelectorAll(elementQuerySelector); 

     if (qs) { 
      var el = event.target, index = -1; 
      while (el && ((index = Array.prototype.indexOf.call(qs, el)) === -1)) { 
       el = el.parentElement; 
      } 

      if (index > -1) { 
       cb.call(el, event); 
      } 
     } 
    }); 
} 



live('click', 'nav .aap a', function(event) { console.log(event); alert('clicked'); }); 
+0

Dziękuję bardzo. Jedną z rzeczy, które chciałbym zaproponować, jest suportowanie 'e.preventDefault()' wewnątrz 'addEventListener'. Jeśli zostanie użyty, musisz go zmienić na 'document.querySelector (elementQuerySelector) .addEventListener (eventType, function (event) {inaczej uniemożliwi ci kliknięcie jakichkolwiek innych elementów na stronie – Lodder

0

Alternatywą wiążącą zdarzenie dynamicznie z konkretnym elementem może być globalny detektor zdarzeń. Tak więc za każdym razem, gdy aktualizujesz DOM o kolejne nowe wydarzenie elementu na tym elemencie, będzie również "catch". Przykład:

var mybuttonlist = document.getElementById('mybuttonlist'); 
 

 
mybuttonlist.addEventListener('click', e=>{ 
 
    if(e.target.nodeName == 'BUTTON'){ 
 
    switch(e.target.name){ 
 
     case 'createnewbutton': 
 
     mybuttonlist.innerHTML += '<li><button name="createnewbutton">Create new button</button></li>'; 
 
     break; 
 
    } 
 
    } 
 
}, false);
ul { 
 
    list-style: none; 
 
    padding: 0; 
 
    margin: 0; 
 
}
<ul id="mybuttonlist"> 
 
    <li><button name="createnewbutton">Create new button</button></li> 
 
</ul>

W tym przykładzie mam detektor zdarzeń na <ul> dla zdarzeń kliknięcia. Tak więc zdarzenie dzieje się dla wszystkich elementów potomnych. Z prostego programu obsługi zdarzeń, który utworzyłem, widać, że łatwo jest dodać więcej logiki, więcej przycisków (z różnymi lub powtarzającymi się nazwami), kotwice itp.

Wchodząc wszystko, możesz dodać eventlistener do dokumentu zamiast element list, przechwytujący wszystkie zdarzenia kliknięcia na stronie, a następnie obsługujący zdarzenia kliknięcia w module obsługi zdarzeń.

Powiązane problemy