Frage Ereignisbindung für dynamisch erstellte Elemente?


Ich habe ein wenig Code, wo ich alle Auswahlfelder auf einer Seite durchlaufen und binden ein .hover Ereignis zu ihnen, um ein bisschen zu drehen mit ihrer Breite auf mouse on/off.

Dies geschieht auf Seite bereit und funktioniert gut.

Das Problem, das ich habe, ist, dass irgendwelche Auswahlkästen, die ich über Ajax oder DOM nach der anfänglichen Schleife hinzufüge, die Ereignisgrenze nicht haben wird.

Ich habe dieses Plugin gefunden (jQuery Live-Abfrage-Plugin), aber bevor ich weitere 5k zu meinen Seiten mit einem Plugin hinzufüge, möchte ich sehen, ob jemand einen Weg kennt, dies entweder mit jQuery direkt oder mit einer anderen Option.


1679
2017-10-14 23:25


Ursprung


Antworten:


Ab jQuery 1.7 du solltest benutzen jQuery.fn.on:

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

Zuvor, war der empfohlene Ansatz zu verwenden live():

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

Jedoch, live() wurde in 1.7 zugunsten von abgelehnt on()und vollständig in 1.9 entfernt. Das live() Unterschrift:

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

... kann durch Folgendes ersetzt werden on() Unterschrift:

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

Zum Beispiel, wenn Ihre Seite dynamisch Elemente mit dem Klassennamen erstellt hat dosomething Sie würden das Ereignis an binden ein Elternteil, das bereits existiert (Dies ist der Nub des Problems hier, Sie brauchen etwas, an das gebunden wird, binden Sie nicht an den dynamischen Inhalt), dies kann (und die einfachste Option) sein document. Denken Sie jedoch daran document möglicherweise nicht die effizienteste Option.

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

Jeder Elternteil, der zum Zeitpunkt der Bindung des Ereignisses existiert, ist in Ordnung. Beispielsweise

$('.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>

1786
2017-08-09 09:51



Es gibt eine gute Erklärung in der Dokumentation von jQuery.fn.on.

Zusamenfassend:

Event-Handler sind nur an die aktuell ausgewählten Elemente gebunden; Sie müssen zu dem Zeitpunkt auf der Seite vorhanden sein, zu dem der Code den Anruf tätigt .on().

Also im folgenden Beispiel #dataTable tbody tr muss 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 als nächstes beschrieben wird.

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

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

Zusätzlich zu ihrer Fähigkeit, Ereignisse auf Nachkommenelementen zu behandeln, die noch nicht erstellt wurden, ist ein weiterer Vorteil von delegierten Ereignissen ihr Potenzial für viel geringeren Overhead, wenn viele Elemente überwacht werden müssen. Auf einer Datentabelle mit 1.000 Zeilen in seiner tbodyIm ersten Codebeispiel wird ein Handler an 1.000 Elemente angehängt.

Ein Delegated-Events-Ansatz (das zweite Codebeispiel) hängt einen Event-Handler nur an ein Element an, das tbody, und das Ereignis muss nur um eine Ebene aufsteigen (aus dem angeklickt tr zu tbody).

Hinweis: Delegierte Ereignisse funktionieren nicht für SVG.


301
2017-12-09 07:59



Das ist ein reines 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);

woher hasClass ist

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

Live-Demo

Der Dank geht an Dave und Sime Vidas

Mit moderneren JS, hasClass kann implementiert werden als:

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

158
2017-10-14 23:31



Sie können Ereignisse zu Objekten hinzufügen, wenn Sie sie erstellen. Wenn Sie mehreren Objekten zu unterschiedlichen Zeiten die gleichen Ereignisse hinzufügen, können Sie eine benannte Funktion erstellen.

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

59
2017-10-14 23:35



Sie können Ihren Ereignisbindungsaufruf einfach in eine Funktion einfügen und dann zweimal aufrufen: einmal im Dokument bereit und einmal nach dem Ereignis, das die neuen DOM-Elemente hinzufügt. Wenn Sie das tun, sollten Sie vermeiden, das gleiche Ereignis zweimal für die vorhandenen Elemente zu binden, so dass Sie entweder die vorhandenen Ereignisse lösen oder (besser) nur an die neu erstellten DOM-Elemente binden müssen. Der Code würde etwa so aussehen:

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

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

// ... add elements ...
addCallbacks($(".myNewElements"))

40
2018-03-21 22:35



Versuchen zu benutzen .live() Anstatt von .bind(); das .live() wird binden .hover zu Ihrer Checkbox, nachdem die Ajax-Anfrage ausgeführt wurde.


37
2017-12-21 07:26



Sie können die Methode live () verwenden, um Elemente (auch neu erstellte) an Ereignisse und Handler wie das Ereignis onclick zu binden.

Hier ist ein Beispielcode, den ich geschrieben habe, wo Sie sehen können, wie die live () -Methode ausgewählte Elemente, sogar 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>

21
2018-01-22 01:06