Pertanyaan Peristiwa mengikat elemen yang dibuat secara dinamis?


Saya memiliki sedikit kode di mana saya perulangan melalui semua kotak pilih pada halaman dan mengikat .hover acara kepada mereka untuk melakukan sedikit twit dengan lebar mereka mouse on/off.

Ini terjadi di halaman siap dan berfungsi dengan baik.

Masalahnya saya adalah bahwa setiap kotak pilih saya tambahkan melalui Ajax atau DOM setelah loop awal tidak akan memiliki acara terikat.

Saya telah menemukan plugin ini (Plugin Query Live jQuery), tetapi sebelum saya menambahkan lagi 5k ke halaman saya dengan sebuah plugin, saya ingin melihat apakah ada yang tahu cara untuk melakukan ini, baik dengan jQuery secara langsung atau dengan opsi lain.


1679
2017-10-14 23:25


asal


Jawaban:


Mulai dari jQuery 1.7 kamu harus menggunakan jQuery.fn.on:

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

Sebelum ini, pendekatan yang direkomendasikan adalah untuk digunakan live():

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

Namun, live() sudah ditinggalkan di 1.7 mendukung on(), dan benar-benar dihapus di 1.9. Itu live() tanda tangan:

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

... dapat diganti dengan yang berikut on() tanda tangan:

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

Misalnya, jika halaman Anda secara dinamis membuat elemen dengan nama kelas dosomething Anda akan mengikat acara tersebut orang tua yang sudah ada (ini adalah inti masalah di sini, Anda perlu sesuatu yang ada untuk diikat, jangan ikat ke konten dinamis), ini bisa (dan opsi termudah) adalah document. Meskipun diingat document mungkin bukan pilihan yang paling efisien.

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

Setiap orang tua yang ada pada saat kejadian terikat baik-baik saja. Sebagai contoh

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

akan berlaku untuk

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

1786
2017-08-09 09:51



Ada penjelasan yang bagus dalam dokumentasi jQuery.fn.on.

Pendeknya:

Penangan kejadian terikat hanya pada elemen yang saat ini dipilih; mereka harus ada di halaman pada saat kode Anda melakukan panggilan ke .on().

Dengan demikian pada contoh berikut #dataTable tbody tr harus ada sebelum kode dibuat.

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

Jika HTML baru sedang disuntikkan ke halaman, lebih baik menggunakan acara yang didelegasikan untuk melampirkan pengendali event, seperti yang dijelaskan selanjutnya.

Peristiwa yang didelegasikan memiliki keuntungan bahwa mereka dapat memproses peristiwa dari elemen keturunan yang ditambahkan ke dokumen di lain waktu. Misalnya, jika tabel ada, tetapi baris ditambahkan secara dinamis menggunakan kode, berikut ini akan menanganinya:

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

Selain kemampuan mereka untuk menangani peristiwa pada unsur-unsur keturunan yang belum diciptakan, keuntungan lain dari peristiwa yang didelegasikan adalah potensi mereka untuk overhead yang jauh lebih rendah ketika banyak elemen harus dipantau. Pada tabel data dengan 1.000 baris di dalamnya tbody, contoh kode pertama menempelkan handler ke 1.000 elemen.

Pendekatan terdelegasi-peristiwa (contoh kode kedua) melampirkan pengendali event hanya satu elemen, yang tbody, dan acara hanya perlu menggelembung satu tingkat (dari yang diklik tr untuk tbody).

catatan: Peristiwa yang didelegasikan tidak berhasil SVG.


301
2017-12-09 07:59



Ini adalah sebuah JavaScript murni solusi tanpa pustaka atau plugin apa pun:

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

dimana hasClass aku s

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

Demo langsung

Kredit diberikan kepada Dave dan Sime Vidas

Menggunakan JS yang lebih modern, hasClass dapat diimplementasikan sebagai:

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

158
2017-10-14 23:31



Anda dapat menambahkan acara ke objek saat Anda membuatnya. Jika Anda menambahkan acara yang sama ke beberapa objek pada waktu yang berbeda, membuat fungsi yang dinamai mungkin adalah cara yang tepat.

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



Anda cukup membungkus acara yang mengikat panggilan menjadi fungsi dan kemudian memanggilnya dua kali: sekali pada dokumen siap dan sekali setelah acara Anda yang menambahkan elemen DOM baru. Jika Anda melakukan itu, Anda akan ingin menghindari pengikatan acara yang sama dua kali pada elemen yang ada sehingga Anda akan perlu baik membatalkan kejadian yang ada atau (lebih baik) hanya mengikat elemen DOM yang baru dibuat. Kode akan terlihat seperti ini:

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

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

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

40
2018-03-21 22:35



Coba gunakan .live() dari pada .bind(); itu .live() akan mengikat .hover ke kotak centang Anda setelah permintaan Ajax dijalankan.


37
2017-12-21 07:26



Anda dapat menggunakan metode live () untuk mengikat elemen (bahkan yang baru dibuat) ke acara dan penangan, seperti acara onclick.

Berikut ini contoh kode yang saya tulis, di mana Anda dapat melihat bagaimana metode live () mengikat elemen yang dipilih, bahkan yang baru dibuat, ke acara:

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