Powiązanie zdarzeń z dynamicznie tworzonymi elementami?

Odpowiedzi na to pytanie są wysiłkiem społeczności. Edytuj istniejące odpowiedzi, aby poprawić ten post. Obecnie nie przyjmuje nowych odpowiedzi ani interakcji.

Mam trochę kodu, w którym przechodzę przez wszystkie Wybierz pola na stronie i powiązaj z nimi Zdarzenie .hover, aby wykonać małe przesunięcie z ich szerokością na mouse on/off.

To dzieje się na stronie gotowe i działa dobrze.

Problem polega na tym, że dowolne pola wyboru, które dodaję przez Ajax lub DOM po początkowej pętli, nie będą miały przypisanego zdarzenia.

Znalazłem tę wtyczkę (jQuery Live Query Plugin ), ale zanim dodam kolejne 5K do moich stron z wtyczką, chcę zobaczyć, czy ktoś zna sposób, aby to zrobić, albo z jQuery bezpośrednio lub za pomocą innej opcji.

Author: Vikrant, 2008-10-14

23 answers

Od jQuery 1.7 należy używać jQuery.fn.on z wypełnionym parametrem selektora:

$(staticAncestors).on(eventName, dynamicChild, function() {});

Explanation:

To się nazywa delegacja zdarzeń i działa w następujący sposób. Zdarzenie jest dołączone do statycznego rodzica (staticAncestors) elementu, który ma być obsługiwany. Ta Obsługa jQuery jest wyzwalana za każdym razem, gdy zdarzenie zostanie wywołane na tym elemencie lub jednym z elementów potomnych. Następnie funkcja obsługi sprawdza, czy element, który wywołał zdarzenie, pasuje do twojego selector (dynamicChild). Gdy jest dopasowanie, wykonywana jest twoja niestandardowa funkcja obsługi.


Przed tym, zalecanym podejściem było użycie live():

$(selector).live( eventName, function(){} );

Jednak live() został wycofany w 1, 7 na rzecz on(), A całkowicie usunięty w 1, 9. live() podpis:

$(selector).live( eventName, function(){} );

... można zastąpić następującym on() podpis:

$(document).on( eventName, selector, function(){} );

Na przykład, jeśli Twoja strona dynamicznie tworzyła elementy z nazwa klasy dosomething przypisywałbyś Zdarzenie do rodzica, który już istnieje (jest to nub problemu, potrzebujesz czegoś, co istnieje, aby powiązać, nie wiązać z dynamiczną zawartością), może to być (i najprostszą opcją) document. Choć miej na uwadze document może nie być najskuteczniejszą opcją .

$(document).on('mouseover mouseout', '.dosomething', function(){
    // what you want to happen when mouseover and mouseout 
    // occurs on elements that match '.dosomething'
});

Każdy rodzic, który istnieje w czasie, gdy zdarzenie jest związane, jest w porządku. Na przykład

$('.buttons').on('click', 'button', function(){
    // do something here
});

Dotyczy

<div class="buttons">
    <!-- <button>s that are generated dynamically and added here -->
</div>
 2363
Author: Popnoodles,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-10 12:38:41

Jest dobre wyjaśnienie w dokumentacji jQuery.fn.on.

W skrócie:

Procedury obsługi zdarzeń są powiązane tylko z aktualnie wybranymi elementami; muszą istnieć na stronie w momencie, gdy twój kod wywoła .on().

Tak więc w poniższym przykładzie {[4] } musi istnieć przed wygenerowaniem kodu.

$("#dataTable tbody tr").on("click", function(event){
    console.log($(this).text());
});

Jeśli nowy HTML jest wstrzykiwany do strony, lepiej jest użyć delegowanych zdarzeń do dołączenia obsługi zdarzenia, ponieważ opisane dalej.

Delegowane zdarzenia mają tę zaletę, że mogą przetwarzać zdarzenia z elementów potomnych, które zostaną dodane do dokumentu w późniejszym czasie. Na przykład, jeśli tabela istnieje, ale wiersze są dodawane dynamicznie za pomocą kodu, zajmie się nią:

$("#dataTable tbody").on("click", "tr", function(event){
    console.log($(this).text());
});

Oprócz możliwości obsługi zdarzeń na elementach potomnych, które nie zostały jeszcze utworzone, kolejną zaletą zdarzeń delegowanych jest ich potencjał znacznie niższy, gdy wiele elementy muszą być monitorowane. W tabeli danych z 1000 wierszami w tbody, pierwszy przykład kodu dołącza obsługę do 1000 elementów.

Podejście delegowane-events (drugi przykład kodu) dołącza obsługę zdarzenia Tylko do jednego elementu, tbody, a zdarzenie musi tylko przesunąć się o jeden poziom (z klikniętego tr do tbody).

Uwaga: delegowane zdarzenia nie działają dla SVG .

 394
Author: Ronen Rabinovici,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-30 21:34:59

To jest czysty JavaScript rozwiązanie bez bibliotek i wtyczek:

document.addEventListener('click', function (e) {
    if (hasClass(e.target, 'bu')) {
        // .bu clicked
        // Do your thing
    } else if (hasClass(e.target, 'test')) {
        // .test clicked
        // Do your other thing
    }
}, false);

Gdzie hasClass jest

function hasClass(elem, className) {
    return elem.className.split(' ').indexOf(className) > -1;
}

live demo

kredyt idzie do Dave i Sime Vidas

Używając bardziej nowoczesnego JS, hasClass można zaimplementować jako:

function hasClass(elem, className) {
    return elem.classList.contains(className);
}
 235
Author: Ram Patra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-27 20:25:06

Możesz dodawać zdarzenia do obiektów podczas ich tworzenia. Jeśli dodajesz te same zdarzenia do wielu obiektów w różnym czasie, dobrym rozwiązaniem może być utworzenie funkcji o nazwie.

var mouseOverHandler = function() {
    // Do stuff
};
var mouseOutHandler = function () {
    // Do stuff
};

$(function() {
    // On the document load, apply to existing elements
    $('select').hover(mouseOverHandler, mouseOutHandler);
});

// This next part would be in the callback from your Ajax call
$("<select></select>")
    .append( /* Your <option>s */ )
    .hover(mouseOverHandler, mouseOutHandler)
    .appendTo( /* Wherever you need the select box */ )
;
 77
Author: nickf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-22 21:41:11

Możesz po prostu zawinąć wywołanie powiązania zdarzeń w funkcję, a następnie wywołać je dwa razy: raz w dokumencie ready i raz po zdarzeniu, które dodaje nowe elementy DOM. Jeśli to zrobisz, będziesz chciał uniknąć powiązania tego samego zdarzenia dwa razy z istniejącymi elementami, więc będziesz musiał albo odłączyć istniejące zdarzenia lub (lepiej) powiązać tylko z nowo utworzonymi elementami DOM. Kod wyglądałby mniej więcej tak:

function addCallbacks(eles){
    eles.hover(function(){alert("gotcha!")});
}

$(document).ready(function(){
    addCallbacks($(".myEles"))
});

// ... add elements ...
addCallbacks($(".myNewElements"))
 51
Author: Greg Borenstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-22 21:41:55

Spróbuj użyć .live() zamiast .bind(); .live() powiąże .hover do twojego pola wyboru po wykonaniu żądania Ajax.

 43
Author: user670265,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-06 20:50:45

Powiązanie zdarzeń na dynamicznie tworzonych elementach

Pojedynczy element:

$(document.body).on('click','.element', function(e) {  });

Element Potomny:

 $(document.body).on('click','.element *', function(e) {  });

Zauważ dodane *. Zdarzenie zostanie wywołane dla wszystkich dzieci tego elementu.

Zauważyłem, że:

$(document.body).on('click','.#element_id > element', function(e) {  });
Już nie działa, ale działa już wcześniej. Używam jQuery od Google CDN , ale nie wiem, czy go zmienili.
 33
Author: MadeInDreams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-22 21:53:15

Wolę używać selektora i nakładam go na dokument.

To wiąże się z dokumentem i będzie miało zastosowanie do elementów, które będą renderowane po załadowaniu strony.

Na przykład:

$(document).on("click", 'selector', function() {
    // Your code here
});
 29
Author: Vatsal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-19 07:29:51

Można użyć metody live() do wiązania elementów (nawet nowo utworzonych) do zdarzeń i procedur obsługi, takich jak Zdarzenie onclick.

Oto przykładowy kod, który napisałem, gdzie możesz zobaczyć, jak metoda live() wiąże wybrane elementy, nawet nowo utworzone, ze zdarzeniami:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Untitled Document</title>
    </head>

    <body>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/jquery-ui.min.js"></script>

        <input type="button" id="theButton" value="Click" />
        <script type="text/javascript">
            $(document).ready(function()
                {
                    $('.FOO').live("click", function (){alert("It Works!")});
                    var $dialog = $('<div></div>').html('<div id="container"><input type ="button" id="CUSTOM" value="click"/>This dialog will show every time!</div>').dialog({
                                                                                                         autoOpen: false,
                                                                                                         tite: 'Basic Dialog'
                                                                                                     });
                    $('#theButton').click(function()
                    {
                        $dialog.dialog('open');
                        return('false');
                    });
                    $('#CUSTOM').click(function(){
                        //$('#container').append('<input type="button" value="clickmee" class="FOO" /></br>');
                        var button = document.createElement("input");
                        button.setAttribute('class','FOO');
                        button.setAttribute('type','button');
                        button.setAttribute('value','CLICKMEE');
                        $('#container').append(button);
                    });
                    /* $('#FOO').click(function(){
                                                     alert("It Works!");
                                                 }); */
            });
        </script>
    </body>
</html>
 27
Author: Fazi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-22 21:44:05

Innym rozwiązaniem jest dodanie słuchacza podczas tworzenia elementu. Zamiast umieścić słuchacza w ciele, umieszczasz słuchacza w elemencie w momencie jego utworzenia:

var myElement = $('<button/>', {
    text: 'Go to Google!'
});

myElement.bind( 'click', goToGoogle);
myElement.append('body');


function goToGoogle(event){
    window.location.replace("http://www.google.com");
}
 22
Author: Martin Da Rosa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-22 21:48:36

odbywa się to poprzez delegację zdarzeń. Event otrzyma bind na elemencie klasy wrapper, ale zostanie delegowany do elementu klasy selektora. Tak to działa.

$('.wrapper-class').on("click", '.selector-class', function() {
    // Your code here
});

I HTML

<div class="wrapper-class">
    <button class="selector-class">
      Click Me!
    </button>
</div>    

#Uwaga: elementem klasy wrapper może być cokolwiek ex. dokument, ciało lub opakowanie. Wrapper powinien już istnieć . Jednak selector niekoniecznie musi być prezentowany w czasie ładowania strony. Może przyjść później, a wydarzenie będzie wiązało się z selector bez porażki .

 22
Author: Mustkeem K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-22 16:01:13

Spróbuj w ten sposób -

$(document).on( 'click', '.click-activity', function () { ... });
 21
Author: Rohit Suthar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-06 07:15:35

Zwróć uwagę na klasę "MAIN" element jest umieszczony, na przykład,

<div class="container">
     <ul class="select">
         <li> First</li>
         <li>Second</li>
    </ul>
</div>

W powyższym scenariuszu głównym obiektem obserwowanym przez jQuery jest "container".

Wtedy będziesz miał w zasadzie nazwy elementów pod kontenerem, takie jak ul, li, i select:

$(document).ready(function(e) {
    $('.container').on( 'click',".select", function(e) {
        alert("CLICKED");
    });
 });
 17
Author: Aslan Kaya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-22 21:56:06

You could use

$('.buttons').on('click', 'button', function(){
    // your magic goes here
});

Lub

$('.buttons').delegate('button', 'click', function() {
    // your magic goes here
});

Te dwie metody są równoważne, ale mają inną kolejność parametrów.

Zobacz: jQuery Delegate Event

 15
Author: Mensur Grišević,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-11 16:16:58

Można dołączyć Zdarzenie do elementu dynamicznie tworzonego za pomocą jQuery(html, attributes).

Od jQuery 1.8, każda metoda instancji jQuery (Metoda jQuery.fn) może być używana jako właściwość obiektu przekazanego do drugi parametr:

function handleDynamicElementEvent(event) {
  console.log(event.type, this.value)
}
// create and attach event to dynamic element
jQuery("<select>", {
    html: $.map(Array(3), function(_, index) {
      return new Option(index, index)
    }),
    on: {
      change: handleDynamicElementEvent
    }
  })
  .appendTo("body");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
 15
Author: guest271314,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-13 12:06:35

Oto dlaczego dynamicznie tworzone elementy nie odpowiadają na kliknięcia:

var body = $("body");
var btns = $("button");
var btnB = $("<button>B</button>");
// `<button>B</button>` is not yet in the document.
// Thus, `$("button")` gives `[<button>A</button>]`.
// Only `<button>A</button>` gets a click listener.
btns.on("click", function () {
  console.log(this);
});
// Too late for `<button>B</button>`...
body.append(btnB);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>

Jako obejście musisz wysłuchać wszystkich kliknięć i sprawdzić element źródłowy:

var body = $("body");
var btnB = $("<button>B</button>");
var btnC = $("<button>C</button>");
// Listen to all clicks and
// check if the source element
// is a `<button></button>`.
body.on("click", function (ev) {
  if ($(ev.target).is("button")) {
    console.log(ev.target);
  }
});
// Now you can add any number
// of `<button></button>`.
body.append(btnB);
body.append(btnC);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>

To się nazywa "Delegacja zdarzeń". Dobra wiadomość, to wbudowana funkcja w jQuery: -)

var i = 11;
var body = $("body");
body.on("click", "button", function () {
  var letter = (i++).toString(36).toUpperCase();
  body.append($("<button>" + letter + "</button>"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>
 12
Author: leaf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-19 12:16:31

Dowolny P arent, który istnieje w momencie wiązania zdarzenia i jeśli twoja strona była dynamicznie tworząca Elementy z przyciskiem o nazwie klasy , powiązałbyś Zdarzenie z rodzicem, który już istnieje

$(document).ready(function(){
  //Particular Parent chield click
  $(".buttons").on("click","button",function(){
    alert("Clicked");
  });  
  
  //Dynamic event bind on button class  
  $(document).on("click",".button",function(){
    alert("Dymamic Clicked");
  });
  $("input").addClass("button");  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="buttons">
  <input type="button" value="1">
  <button>2</button>
  <input type="text">
  <button>3</button>  
  <input type="button" value="5">  
  </div>
<button>6</button>
 11
Author: Ankit Kathiriya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-18 08:48:51

Powiązać Zdarzenie z rodzicem, który już istnieje:

$(document).on("click", "selector", function() {
    // Your code here
});
 11
Author: truongnm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-08 02:29:14

Inne elastyczne rozwiązanie do tworzenia elementów i wiązania zdarzeń (source)

// creating a dynamic element (container div)
var $div = $("<div>", {id: 'myid1', class: 'myclass'});

//creating a dynamic button
 var $btn = $("<button>", { type: 'button', text: 'Click me', class: 'btn' });

// binding the event
 $btn.click(function () { //for mouseover--> $btn.on('mouseover', function () {
    console.log('clicked');
 });

// append dynamic button to the dynamic container
$div.append($btn);

// add the dynamically created element(s) to a static element
$("#box").append($div);

Uwaga: spowoduje to utworzenie instancji obsługi zdarzeń dla każdego elementu (może mieć wpływ na wydajność, gdy jest używana w pętlach)

 6
Author: Prasad De Silva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-27 04:21:48

Użyj metody {[0] } jQuery http://api.jquery.com/on / aby dołączyć procedury obsługi zdarzeń do elementu aktywnego.

Również od wersji 1.9 .live() metoda jest usuwana.

 5
Author: Kalpesh Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-30 09:07:46

Wolę, aby słuchacze zdarzeń były rozmieszczone w modularny sposób niż skryptowanie słuchacza zdarzeń poziomu document. Tak, lubię poniżej. Uwaga, nie można przecenić elementu z tym samym słuchaczem zdarzeń, więc nie martw się o dołączenie słuchacza więcej niż raz - tylko jeden kij.

var iterations = 4;
var button;
var body = document.querySelector("body");

for (var i = 0; i < iterations; i++) {
    button = document.createElement("button");
    button.classList.add("my-button");
    button.appendChild(document.createTextNode(i));
    button.addEventListener("click", myButtonWasClicked);
    body.appendChild(button);
}

function myButtonWasClicked(e) {
    console.log(e.target); //access to this specific button
}
 5
Author: Ronnie Royston,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-08 02:53:27
<html>
    <head>
        <title>HTML Document</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    </head>

    <body>
        <div id="hover-id">
            Hello World
        </div>

        <script>
            jQuery(document).ready(function($){
                $(document).on('mouseover', '#hover-id', function(){
                    $(this).css('color','yellowgreen');
                });

                $(document).on('mouseout', '#hover-id', function(){
                    $(this).css('color','black');
                });
            });
        </script>
    </body>
</html>
 0
Author: Fakhrul Hasan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-27 15:42:58

Szukałem rozwiązania, aby $.bind i $.unbind działały bez problemów w dynamicznie dodawanych elementach.

Jako on () robi sztuczkę, aby dołączyć zdarzenia, w celu stworzenia fałszywego unbind na tych, do których przyszedłem:

const sendAction = function(e){ ... }
// bind the click
$('body').on('click', 'button.send', sendAction );

// unbind the click
$('body').on('click', 'button.send', function(){} );
 0
Author: Evhz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-18 00:13:34