it-swarm.com.de

Ereignisbindung für dynamisch erzeugte Elemente?

Ich habe ein bisschen Code, in dem ich alle Auswahlfelder auf einer Seite durchlaufe und ein .hover -Ereignis an sie binde, um ein bisschen mit ihrer Breite auf mouse on/off herumzuspielen.

Dies geschieht auf der Seite bereit und funktioniert einwandfrei.

Das Problem ist, dass bei Auswahlfeldern, die ich über Ajax oder DOM nach der ersten Schleife hinzufüge, das Ereignis nicht gebunden wird.

Ich habe dieses Plugin gefunden ( jQuery Live Query Plugin ), aber bevor ich mit einem Plugin weitere 5k zu meinen Seiten hinzufüge, möchte ich wissen, ob jemand eine Möglichkeit hat, dies entweder direkt mit jQuery oder mit jQuery zu tun durch eine andere Option.

1677
Eli

Ab jQuery 1.7 sollten Sie jQuery.fn.on verwenden:

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

Vor diesem wurde empfohlen, live() zu verwenden:

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

live() wurde jedoch in 1.7 zugunsten von on() veraltet und in 1.9 vollständig entfernt. Die live() Signatur:

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

... kann durch die folgende on() Signatur ersetzt werden:

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

Wenn Ihre Seite beispielsweise dynamisch Elemente mit dem Klassennamen dosomething erstellt, binden Sie das Ereignis an ein übergeordnetes Element , das bereits vorhanden ist (this Ist der Kern des Problems hier, müssen Sie etwas vorhandenes binden, nicht an den dynamischen Inhalt binden. Dies kann sein (und die einfachste Option ist document. Bedenken Sie jedoch, dass document möglicherweise nicht die effizienteste Option ist .

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

Jedes Elternteil, das zum Zeitpunkt der Bindung des Ereignisses existiert, ist in Ordnung. Zum Beispiel

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

würde gelten für

_<div class="buttons">
    <!-- <button>s that are generated dynamically and added here -->
</div>
_
2084
dev.e.loper

Die Dokumentation von jQuery.fn.on enthält eine gute Erklärung.

Zusamenfassend:

Ereignishandler sind nur an die aktuell ausgewählten Elemente gebunden. Sie müssen auf der Seite vorhanden sein, wenn Ihr Code .on() aufruft.

Daher muss im folgenden Beispiel _#dataTable tbody tr_ vorhanden sein, bevor der Code generiert wird.

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

Wenn neues HTML in die Seite eingefügt wird, ist es vorzuziehen, delegierte Ereignisse zu verwenden, um einen Ereignishandler anzuhängen, wie im Folgenden beschrieben.

Delegierte Ereignisse haben den Vorteil, dass sie Ereignisse von untergeordneten Elementen verarbeiten können, die zu einem späteren Zeitpunkt zum Dokument hinzugefügt werden. Wenn die Tabelle beispielsweise vorhanden ist, die Zeilen jedoch mithilfe von Code dynamisch hinzugefügt werden, wird dies wie folgt behandelt:

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

Ein weiterer Vorteil delegierter Ereignisse besteht darin, dass sie nicht nur Ereignisse für untergeordnete Elemente verarbeiten können, die noch nicht erstellt wurden, sondern auch einen wesentlich geringeren Overhead aufweisen, wenn viele Elemente überwacht werden müssen. In einer Datentabelle mit 1.000 Zeilen in tbody wird im ersten Codebeispiel ein Handler an 1.000 Elemente angehängt.

Bei einem Delegated-Events-Ansatz (im zweiten Codebeispiel) wird eine Ereignisbehandlungsroutine nur einem Element zugeordnet, dem tbody, und das Ereignis muss nur eine Ebene aufblähen (vom angeklickten tr zum tbody).

Hinweis: Delegierte Ereignisse funktionieren nicht für SVG .

350

Dies ist eine reine JavaScript-Lösung ohne Bibliotheken oder Plugins:

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

wo hasClass ist

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

Live demo

Dank geht an Dave und Sime Vidas

Mit modernerem JS kann hasClass implementiert werden als:

function hasClass(elem, className) {
    return elem.classList.contains(className);
}
195
Ram Patra

Sie können Objekten beim Erstellen Ereignisse hinzufügen. Wenn Sie dieselben Ereignisse zu verschiedenen Zeiten zu mehreren Objekten hinzufügen, ist das Erstellen einer benannten Funktion möglicherweise der richtige Weg.

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 */ )
;
68
nickf

Sie können Ihren Ereignisbindungsaufruf einfach in eine Funktion einbinden und dann zweimal aufrufen: einmal für das Dokument bereit und einmal nach dem Ereignis, bei dem die neuen DOM-Elemente hinzugefügt werden. Wenn Sie dies tun, möchten Sie vermeiden, dass dasselbe Ereignis zweimal an die vorhandenen Elemente gebunden wird, sodass Sie entweder die Bindung der vorhandenen Ereignisse aufheben oder (besser) nur an die neu erstellten DOM-Elemente binden müssen. Der Code würde ungefähr so ​​aussehen:

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

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

// ... add elements ...
addCallbacks($(".myNewElements"))
47
Greg Borenstein

Versuchen Sie, .live() anstelle von .bind() zu verwenden; Das .live() bindet .hover an Ihr Kontrollkästchen, nachdem die Ajax-Anforderung ausgeführt wurde.

40
user670265

Ereignisbindung für dynamisch erstellte Elemente

Einzelelement:

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

Untergeordnetes Element:

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

Beachten Sie den hinzugefügten *. Ein Ereignis wird für alle untergeordneten Elemente dieses Elements ausgelöst.

Ich habe bemerkt, dass:

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

Es funktioniert nicht mehr, aber es hat vorher funktioniert. Ich habe jQuery von Google verwendet CDN , aber ich weiß nicht, ob sie es geändert haben.

24
MadeInDreams

Mit der Methode live () können Sie Elemente (auch neu erstellte) an Ereignisse und Handler wie das Ereignis onclick binden.

Hier ist ein Beispielcode, den ich geschrieben habe, in dem Sie sehen können, wie die live () -Methode ausgewählte Elemente, auch neu erstellte, an Ereignisse bindet:

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

Ich bevorzuge die Verwendung des Selektors und wende ihn auf das Dokument an.

Dies bindet sich an das Dokument und gilt für die Elemente, die nach dem Laden der Seite gerendert werden.

Zum Beispiel:

$(document).on("click", $(selector), function() {
    // Your code here
});
19
Vatsal

Eine andere Lösung besteht darin, den Listener beim Erstellen des Elements hinzuzufügen. Anstatt den Listener in den Body zu setzen, setzen Sie den Listener in dem Moment in das Element, in dem Sie es erstellen:

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

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


function goToGoogle(event){
    window.location.replace("http://www.google.com");
}
18
Martin Da Rosa

Sie können ein Ereignis an ein Element anhängen, wenn Sie es dynamisch mit jQuery(html, attributes) erstellen.

Ab jQuery 1.8 kann jede jQuery-Instanzmethode (eine Methode von jQuery.fn) als Eigenschaft des an die zweite übergebenen Objekts verwendet werden Parameter:

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

Beachten Sie die Klasse "MAIN", in der sich das Element befindet, z. B.

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

Im obigen Szenario ist das MAIN-Objekt, das von der jQuery überwacht wird, "container".

Dann haben Sie im Grunde genommen Elementnamen unter dem Container wie ul, li und select:

$(document).ready(function(e) {
    $('.container').on( 'click',".select", function(e) {
        alert("CLICKED");
    });
 });
13
Aslan Kaya

du könntest benutzen

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

oder

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

diese beiden Methoden sind äquivalent, weisen jedoch eine unterschiedliche Reihenfolge der Parameter auf.

siehe: jQuery Delegate Event

12

Versuchen Sie es so -

$(document).on( 'click', '.click-activity', function () { ... });
10
Rohit Suthar

Aus folgendem Grund reagieren dynamisch erstellte Elemente nicht auf Klicks:

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>

Um dies zu umgehen, müssen Sie alle Klicks abhören und das Quellelement überprüfen:

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>

Dies wird als "Event Delegation" bezeichnet. Gute Nachricht, es ist eine eingebaute Funktion in 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>
10
leaf

Dies erfolgt durch Ereignisdelegation . Das Ereignis wird an das Element der Wrapper-Klasse gebunden, aber an das Element der Selector-Klasse delegiert. So funktioniert es.

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

Hinweis:

wrapper-Klasse-Element kann alles ex sein. Dokument, Körper oder Ihre Hülle. Wrapper sollte bereits existieren. selector muss jedoch nicht unbedingt zum Zeitpunkt des Ladens der Seite vorhanden sein. Es kann später kommen und das Ereignis wird an selectorohne Fehler gebunden.

9
Asif J

Jedes p nicht vorhanden zum Zeitpunkt der Bindung des Ereignisses und wenn Ihre Seite dynamisch erstellende Elemente mit dem Klassennamen Schaltfläche wäre, würden Sie das binden Ereignis an ein Elternteil, das bereits vorhanden ist

$(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>
8
Ankit Kathiriya

Binden Sie das Ereignis an ein bereits vorhandenes übergeordnetes Element:

$(document).on("click", "selector", function() {
    // Your code here
});
5
truongnm

Verwenden Sie die .on() -Methode von jQuery http://api.jquery.com/on/ , um Ereignishandler an das Live-Element anzuhängen.

Ab Version 1.9 wurde auch die Methode .live() entfernt.

4
Kalpesh Patel

Eine weitere flexible Lösung zum Erstellen von Elementen und zum Binden von Ereignissen ( 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);

Hinweis: Dadurch wird für jedes Element eine Ereignishandlerinstanz erstellt (kann die Leistung bei Verwendung in Schleifen beeinträchtigen)

2
Prasad De Silva

Ich bevorzuge es, Ereignis-Listener in einer modularen Funktionsweise implementieren zu lassen, anstatt einen Ereignis-Listener auf document -Ebene zu skripten. Also, ich mag unten. Beachten Sie, dass Sie ein Element nicht mit demselben Ereignis-Listener überzeichnen können. Sorgen Sie sich also nicht, dass Sie einen Listener mehr als einmal anfügen müssen - nur ein Stick.

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
}
2
Ron Royston