Domanda Associazione di eventi su elementi creati dinamicamente?


Ho un po 'di codice in cui sono in loop tutte le caselle di selezione in una pagina e vincolante a .hover evento a loro di fare un po 'di giocherellare con la loro larghezza mouse on/off.

Questo succede a pagina pronta e funziona bene.

Il problema che ho è che ogni casella di selezione che aggiungo tramite Ajax o DOM dopo il ciclo iniziale non avrà l'evento associato.

Ho trovato questo plugin (jQuery Live Query Plugin), ma prima di aggiungere un altro 5k alle mie pagine con un plugin, voglio vedere se qualcuno conosce un modo per farlo, sia con jQuery direttamente o con un'altra opzione.


1679
2017-10-14 23:25


origine


risposte:


A partire da jQuery 1.7 dovresti usare jQuery.fn.on:

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

Prima di questo, l'approccio raccomandato era quello di utilizzare live():

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

Però, live() è stato deprecato in 1.7 a favore di on()e completamente rimosso in 1.9. Il live() firma:

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

... può essere sostituito con il seguente on() firma:

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

Ad esempio, se la tua pagina creava dinamicamente elementi con il nome della classe dosomething dovresti associare l'evento a un genitore che esiste già (questo è il nocciolo del problema qui, hai bisogno di qualcosa che esiste per associare, non legare al contenuto dinamico), questo può essere (e l'opzione più semplice) è document. Anche se tieni a mente document potrebbe non essere l'opzione più efficiente.

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

Qualsiasi genitore esistente al momento in cui l'evento è associato va bene. Per esempio

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

si applicherebbe a

<div class="buttons">
    <!-- <button>s that are generated dynamically and added here -->
</div>

1786
2017-08-09 09:51



C'è una buona spiegazione nella documentazione di jQuery.fn.on.

In breve:

I gestori di eventi sono associati solo agli elementi attualmente selezionati; devono esistere sulla pagina nel momento in cui il tuo codice effettua la chiamata .on().

Quindi nel seguente esempio #dataTable tbody tr deve esistere prima che il codice venga generato.

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

Se il nuovo codice HTML viene iniettato nella pagina, è preferibile utilizzare gli eventi delegati per collegare un gestore di eventi, come descritto di seguito.

Eventi delegati hanno il vantaggio di poter elaborare eventi da elementi discendenti che vengono aggiunti al documento in un secondo momento. Ad esempio, se la tabella esiste, ma le righe vengono aggiunte dinamicamente utilizzando il codice, il seguente lo gestirà:

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

Oltre alla loro capacità di gestire eventi su elementi discendenti che non sono ancora stati creati, un altro vantaggio degli eventi delegati è il loro potenziale per un sovraccarico molto più basso quando molti elementi devono essere monitorati. Su una tabella di dati con 1.000 righe nella sua tbody, il primo esempio di codice allega un gestore a 1.000 elementi.

Un approccio con eventi delegati (il secondo esempio di codice) allega un gestore di eventi a un solo elemento, il tbody, e l'evento deve solo diventare un livello superiore (dal clic tr a tbody).

Nota: Gli eventi delegati non funzionano per SVG.


301
2017-12-09 07:59



Questo è un puro JavaScript soluzione senza librerie o plugin:

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

dove hasClass è

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

Dimostrazione dal vivo

Il merito va a Dave e Sime Vidas

Usando JS più moderno, hasClass può essere implementato come:

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

158
2017-10-14 23:31



Puoi aggiungere eventi agli oggetti quando li crei. Se stai aggiungendo gli stessi eventi a più oggetti in momenti diversi, la creazione di una funzione con nome potrebbe essere la soluzione giusta.

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



Potresti semplicemente racchiudere il richiamo dell'evento in una funzione e quindi invocarlo due volte: una volta sul documento pronto e una volta dopo l'evento che aggiunge i nuovi elementi DOM. Se lo fai, eviterai di legare lo stesso evento due volte sugli elementi esistenti, quindi è necessario separare gli eventi esistenti o (meglio) legarli solo agli elementi DOM che sono stati appena creati. Il codice sarebbe simile a questo:

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

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

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

40
2018-03-21 22:35



Prova ad usare .live() invece di .bind(); il .live() legherà .hover alla tua casella di controllo dopo l'esecuzione della richiesta Ajax.


37
2017-12-21 07:26



È possibile utilizzare il metodo live () per associare elementi (anche quelli appena creati) ad eventi e gestori, come l'evento onclick.

Ecco un esempio di codice che ho scritto, in cui puoi vedere come il metodo live () lega gli elementi scelti, anche quelli appena creati, agli eventi:

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