Dari mana ini berasal
Ketika saya pertama kali belajar jQuery, saya biasanya melampirkan acara seperti ini:
$('.my-widget a').click(function() {
$(this).toggleClass('active');
});
Setelah mempelajari lebih lanjut tentang kecepatan pemilih dan delegasi acara, saya membaca di beberapa tempat bahwa "delegasi acara jQuery akan membuat kode Anda lebih cepat." Jadi saya mulai menulis kode seperti ini:
$('.my-widget').on('click','a',function() {
$(this).toggleClass('active');
});
Ini juga merupakan cara yang disarankan untuk mereplikasi perilaku peristiwa .live () yang tidak digunakan lagi. Yang penting bagi saya karena banyak situs saya secara dinamis menambah / menghapus widget setiap saat. Namun di atas tidak berperilaku persis seperti .live (), karena hanya elemen yang ditambahkan ke wadah yang sudah ada '.my-widget' yang akan mendapatkan perilaku. Jika saya menambahkan secara dinamis blok html lain setelah kode tersebut berjalan, elemen-elemen itu tidak akan membuat acara terikat dengannya. Seperti ini:
setTimeout(function() {
$('body').append('<div class="my-widget"><a>Click does nothing</a></div>');
}, 1000);
Apa yang ingin saya capai:
- perilaku lama .live () // yang berarti melampirkan peristiwa ke elemen yang belum ada
- manfaat .on ()
- kinerja tercepat untuk mengikat acara
- Cara sederhana untuk mengelola acara
Saya sekarang melampirkan semua acara seperti ini:
$(document).on('click.my-widget-namespace', '.my-widget a', function() {
$(this).toggleClass('active');
});
Yang sepertinya memenuhi semua tujuan saya. (Ya itu lebih lambat di IE untuk beberapa alasan, tidak tahu mengapa?) Ini cepat karena hanya satu peristiwa diikat ke elemen tunggal dan pemilih sekunder hanya dievaluasi ketika peristiwa terjadi (perbaiki saya jika ini salah di sini). Namespace mengagumkan karena membuatnya lebih mudah untuk beralih pendengar acara.
Solusi / Pertanyaan Saya
Jadi saya mulai berpikir bahwa acara jQuery harus selalu terikat ke $ (dokumen).
Apakah ada alasan mengapa Anda tidak ingin melakukan ini?
Mungkinkah ini dianggap praktik terbaik? Jika tidak, mengapa?
Jika Anda sudah membaca semua ini, terima kasih. Saya menghargai setiap / semua umpan balik / wawasan.
Asumsi:
- Menggunakan jQuery yang mendukung
.on()
// setidaknya versi 1.7 - Anda ingin acara tersebut ditambahkan ke konten yang ditambahkan secara dinamis
Bacaan / Contoh:
Jawaban:
Tidak - Anda TIDAK boleh mengikat semua penangan acara yang didelegasikan ke
document
objek. Itu mungkin skenario berkinerja terburuk yang bisa Anda buat.Pertama, delegasi acara tidak selalu membuat kode Anda lebih cepat. Dalam beberapa kasus, ini menguntungkan dan dalam beberapa kasus tidak. Anda harus menggunakan delegasi acara ketika Anda benar-benar membutuhkan delegasi acara dan ketika Anda mendapat manfaat darinya. Jika tidak, Anda harus mengikat penangan acara langsung ke objek tempat acara terjadi karena ini umumnya akan lebih efisien.
Kedua, Anda TIDAK boleh mengikat semua acara yang didelegasikan di tingkat dokumen. Inilah sebabnya mengapa
.live()
sudah usang karena ini sangat tidak efisien ketika Anda memiliki banyak peristiwa terikat dengan cara ini. Untuk penanganan acara yang didelegasikan, JAUH lebih efisien untuk mengikat mereka ke induk terdekat yang tidak dinamis.Ketiga, tidak semua acara bekerja atau semua masalah dapat diselesaikan dengan delegasi. Misalnya, jika Anda ingin mencegat peristiwa utama pada kontrol input dan memblokir kunci yang tidak valid agar tidak dimasukkan ke dalam kontrol input, Anda tidak dapat melakukan itu dengan penanganan acara yang didelegasikan karena pada saat acara muncul hingga penangan yang didelegasikan, itu sudah telah diproses oleh kontrol input dan sudah terlambat untuk mempengaruhi perilaku itu.
Inilah saat-saat ketika delegasi acara diperlukan atau menguntungkan:
Untuk memahami ini sedikit lagi, orang perlu memahami bagaimana penangan event yang didelegasikan jQuery bekerja. Ketika Anda memanggil sesuatu seperti ini:
Itu menginstal pengendali event jQuery generik pada
#myParent
objek. Ketika sebuah event klik muncul hingga pengendali event yang didelegasikan ini, jQuery harus melihat daftar handler event yang didelegasikan yang dilampirkan pada objek ini dan melihat apakah elemen yang berasal dari event tersebut cocok dengan salah satu pemilih dalam handler event yang didelegasikan.Karena penyeleksi dapat terlibat secara adil, ini berarti bahwa jQuery harus mengurai setiap pemilih dan kemudian membandingkannya dengan karakteristik target acara asli untuk melihat apakah itu cocok dengan setiap pemilih. Ini bukan operasi yang murah. Bukan masalah besar jika hanya ada satu di antara mereka, tetapi jika Anda menempatkan semua penyeleksi Anda pada objek dokumen dan ada ratusan penyeleksi untuk dibandingkan dengan setiap peristiwa yang menggelegak, ini secara serius dapat mulai menghambat kinerja penanganan acara.
Untuk alasan ini, Anda ingin mengatur penangan acara yang didelegasikan Anda sehingga penangan acara yang didelegasikan sedekat mungkin dengan objek target. Ini berarti bahwa lebih sedikit acara akan muncul melalui masing-masing pengendali acara yang didelegasikan, sehingga meningkatkan kinerja. Menempatkan semua acara yang didelegasikan pada objek dokumen adalah kinerja yang paling buruk karena semua acara yang digelembungkan harus melalui semua penangan acara yang didelegasikan dan dievaluasi terhadap semua penyeleksi acara yang mungkin didelegasikan. Inilah sebabnya mengapa
.live()
usang karena ini adalah apa yang.live()
dilakukan dan terbukti sangat tidak efisien.Jadi, untuk mencapai kinerja yang dioptimalkan:
sumber
$(document).on('click', '[myCustomAttr]', function () { ... });
?document
, atau mengikat ke pilihan yang lebih spesifikpage:load
dan membatalkan ikatan peristiwa inipage:after-remove
? HmmmDelegasi acara adalah teknik untuk menulis penangan Anda sebelum elemen tersebut benar-benar ada di DOM. Metode ini memiliki kekurangannya sendiri dan harus digunakan hanya jika Anda memiliki persyaratan seperti itu.
Kapan Anda harus menggunakan delegasi acara?
Mengapa Anda tidak menggunakan delegasi acara?
PS: Bahkan untuk konten dinamis Anda tidak harus menggunakan metode delegasi acara jika Anda mengikat pawang setelah konten dimasukkan ke DOM. (Jika konten dinamis ditambahkan tidak sering dihapus / ditambahkan kembali)
sumber
Rupanya, delegasi acara sebenarnya direkomendasikan sekarang. setidaknya untuk vanilla js.
https://gomakethings.com/why-event-delegation-is-a-better-way-to-listen-for-events-in-vanilla-js/
"Kinerja Web # Rasanya seperti mendengarkan setiap klik dalam dokumen akan berdampak buruk bagi kinerja, tetapi sebenarnya lebih berkinerja daripada memiliki banyak pendengar acara di setiap item."
sumber
Saya ingin menambahkan beberapa komentar dan argumen balasan untuk jawaban jfriend00. (Sebagian besar hanya pendapat saya berdasarkan perasaan saya)
Meskipun benar bahwa kinerja mungkin sedikit lebih baik jika Anda hanya akan mendaftar dan mengadakan satu elemen, saya percaya itu tidak membebani manfaat skalabilitas yang dibawa oleh delegasi. Saya juga percaya browser akan menangani ini lebih dan lebih efisien, meskipun saya tidak punya bukti tentang ini. Menurut pendapat saya, delegasi acara adalah jalan yang harus dilalui!
Saya agak setuju dengan ini. Jika Anda 100% yakin bahwa suatu peristiwa hanya akan terjadi di dalam wadah, masuk akal untuk mengikat acara ke wadah ini, tapi saya masih akan berdebat menentang acara mengikat ke elemen pemicu secara langsung.
Ini tidak benar. Silakan lihat kode iniPen: https://codepen.io/pwkip/pen/jObGmjq
Ini menggambarkan bagaimana Anda dapat mencegah pengguna mengetik dengan mendaftarkan acara penekanan tombol pada dokumen.
Saya ingin membalas dengan kutipan ini dari https://ehsangazar.com/optimizing-javascript-event-listeners-for-performance-e28406ad406c
Event delegation promotes binding as few DOM event handlers as possible, since each event handler requires memory. For example, let’s say that we have an HTML unordered list we want to bind event handlers to. Instead of binding a click event handler for each list item (which may be hundreds for all we know), we bind one click handler to the parent unordered list itself.
Juga, googling untuk
performance cost of event delegation google
mengembalikan hasil lebih banyak dalam mendukung delegasi acara.Di mana ini didokumentasikan? Jika itu benar, maka jQuery tampaknya menangani delegasi dengan cara yang sangat tidak efisien, dan kemudian argumen-argumen saya seharusnya hanya diterapkan pada vanilla JS.
Namun: Saya ingin mencari sumber resmi yang mendukung klaim ini.
:: EDIT ::
Sepertinya jQuery memang melakukan peristiwa yang menggelegak dengan cara yang sangat tidak efisien (karena mereka mendukung IE8) https://api.jquery.com/on/#event-performance
Jadi sebagian besar argumen saya di sini hanya berlaku untuk vanilla JS dan browser modern.
sumber