jQuery: lebih dari satu penangan untuk acara yang sama

137

Apa yang terjadi jika saya mengikat dua penangan kejadian ke acara yang sama untuk elemen yang sama?

Sebagai contoh:

var elem = $("...")
elem.click(...);
elem.click(...);

Apakah pawang terakhir "menang", atau apakah kedua pawang akan lari?

flybywire
sumber

Jawaban:

170

Kedua penangan akan berjalan, model peristiwa jQuery memungkinkan beberapa penangan pada satu elemen, oleh karena itu penangan selanjutnya tidak menggantikan penangan yang lebih lama.

Pawang akan mengeksekusi sesuai urutan mereka terikat .

Russ Cam
sumber
1
apa yang terjadi dengan cara asli? dan bagaimana penduduk asli tahu cara menghapus yang spesifik?
SuperUberDuper
1
Menurut DOM Level 3 (mereferensikan spesifikasi HTML 5), pengendali acara dijalankan sesuai urutan pendaftarannya - w3.org/TR/DOM-Level-3-Events/#event-phase dan w3.org/TR/ 2014 / REC-html5-20141028 /… . Penangan acara dapat dihapus dengan memberikan referensi ke penangan yang telah terdaftar
Russ Cam
@RussCam apa yang terjadi jika penangan yang sama terikat lebih dari satu kali katakan saja jQuery('.btn').on('click',handlerClick);dipanggil di berbagai tempat tanpa benar-benar di .offmana pun?
techie_28
Perhatikan bahwa untuk widget widgetfactory jQueryUI, ini tidak benar jika Anda menyetel penangan sebagai opsi. Agar penangan lama dan baru dipanggil, Anda perlu menggunakan bindmetode ini. Lihat ini untuk detailnya: learn.jquery.com/jquery-ui/widget-factory/…
Michael Scheper
@MichaelScheper merasa bebas untuk mengedit jawaban dan memperbarui dengan info tambahan
Russ Cam
36

Misalkan Anda memiliki dua penangan, f dan g , dan ingin memastikan bahwa mereka dieksekusi dalam urutan yang diketahui dan tetap, maka rangkum saja:

$("...").click(function(event){
  f(event);
  g(event);
});

Dengan cara ini (dari perspektif jQuery) hanya ada satu penangan, yang memanggil f dan g dalam urutan yang ditentukan.

Stephan202
sumber
3
+1, enkapsulasi di dalam suatu fungsi adalah cara yang harus dilakukan. Dan logika kondisional yang lebih baik dapat dimasukkan di dalam fungsi handler untuk mengontrol kejadian yang dipicu.
Gordon Potter
Kumpulan penangan yang urutannya ditentukan secara terprogram.
Aaron Blenkush
17

.bind () jQuery diaktifkan dalam urutan itu terikat :

Ketika sebuah kejadian mencapai sebuah elemen, semua penangan yang terikat ke tipe kejadian untuk elemen tersebut akan diaktifkan. Jika ada beberapa penangan yang terdaftar, mereka akan selalu mengeksekusi sesuai urutan mereka terikat. Setelah semua penangan dijalankan, acara berlanjut di sepanjang jalur penyebaran acara normal.

Sumber: http://api.jquery.com/bind/

Karena fungsi jQuery yang lain (mis. .click()) Adalah pintasan .bind('click', handler), saya kira fungsi-fungsi itu juga dipicu dalam urutan mengikatnya.

allicarn
sumber
11

Anda harus bisa menggunakan chaining untuk mengeksekusi event secara berurutan, misalnya:

$('#target')
  .bind('click',function(event) {
    alert('Hello!');
  })
  .bind('click',function(event) {
    alert('Hello again!');
  })
  .bind('click',function(event) {
    alert('Hello yet again!');
  });

Saya kira kode di bawah ini melakukan hal yang sama

$('#target')
      .click(function(event) {
        alert('Hello!');
      })
      .click(function(event) {
        alert('Hello again!');
      })
      .click(function(event) {
        alert('Hello yet again!');
      });

Sumber: http://www.peachpit.com/articles/article.aspx?p=1371947&seqNum=3

TFM juga mengatakan:

Ketika sebuah kejadian mencapai sebuah elemen, semua penangan yang terikat ke tipe kejadian untuk elemen tersebut akan diaktifkan. Jika ada beberapa penangan yang terdaftar, mereka akan selalu mengeksekusi sesuai urutan mereka terikat. Setelah semua penangan dijalankan, acara berlanjut di sepanjang jalur penyebaran acara normal.

anddoutoi
sumber
1
Baik kode itu maupun artikel itu tidak menentukan urutan eksekusi penangan. Ya, itulah urutan event binding akan terjadi, tetapi urutan yang dipanggil oleh event handler masih belum ditentukan secara resmi.
Crescent Fresh
ehh? bagaimana dengan "Sekarang saat event klik terjadi, event handler pertama akan dipanggil, diikuti oleh yang kedua, diikuti oleh yang ketiga." tidak jelas?
anddoutoi
dan ya, saya tahu bahwa rekomendasi resmi tidak mendefinisikan ini dan PPK telah membuktikan bahwa pelaksanaan acara itu acak tetapi mungkin jQuery telah memperbaikinya ^^
anddoutoi
Ahh, melewatkan kalimat itu. Faktanya, penulis salah informasi. jQuery belum "memperbaiki" ini. Karena spesifikasi tidak secara resmi menentukan pesanan, secara teknis tidak ada yang perlu diperbaiki.
Crescent Fresh
5
@CrescentFresh: Maaf atas jawaban yang terlambat, saya baru saja melihat pertanyaannya, tetapi saya ingin Anda menunjukkan tautannya , ini adalah dokumentasi resmi jQuery dan dengan jelas mengatakan bahwaWhen an event reaches an element, all handlers bound to that event type for the element are fired. If there are multiple handlers registered, they will always execute in the order in which they were bound. After all handlers have executed, the event continues along the normal event propagation path.
Razort4x
2

Kedua penangan dipanggil.

Anda mungkin berpikir tentang pengikatan acara inline (misalnya "onclick=..."), di mana kelemahan besar hanya satu penangan yang dapat ditetapkan untuk sebuah acara.

jQuery sesuai dengan model registrasi event DOM Level 2 :

Model Peristiwa DOM memungkinkan pendaftaran beberapa event listener pada satu EventTarget. Untuk mencapai ini, event listener tidak lagi disimpan sebagai nilai atribut

Crescent Fresh
sumber
@ Kaya: urutan secara resmi belum ditentukan.
Crescent Fresh
2

Berhasil berhasil menggunakan 2 metode: enkapsulasi Stephan202 dan beberapa event listener. Saya memiliki 3 tab pencarian, mari kita tentukan id teks masukan mereka dalam Array:

var ids = new Array("searchtab1", "searchtab2", "searchtab3");

Ketika konten searchtab1 berubah, saya ingin memperbarui searchtab2 dan searchtab3. Lakukan dengan cara ini untuk enkapsulasi:

for (var i in ids) {
    $("#" + ids[i]).change(function() {
        for (var j in ids) {
            if (this != ids[j]) {
                $("#" + ids[j]).val($(this).val());
            }
        }
    });
}

Beberapa pendengar acara:

for (var i in ids) {
    for (var j in ids) {
        if (ids[i] != ids[j]) {
            $("#" + ids[i]).change(function() {
                $("#" + ids[j]).val($(this).val());
            });
        }
    }
}

Saya suka kedua metode tersebut, tetapi programmer memilih enkapsulasi, namun pendengar beberapa acara juga bekerja. Kami menggunakan Chrome untuk mengujinya.

GeneralElektrix
sumber
1

Ada solusi untuk menjamin bahwa satu penangan terjadi setelah penangan lainnya: pasang penangan kedua ke elemen penampung dan biarkan acara menggelembung. Di penangan yang dilampirkan ke penampung, Anda dapat melihat event.target dan melakukan sesuatu jika itu yang Anda minati.

Kasar, mungkin, tapi pasti berhasil.

David
sumber
0

jquery akan mengeksekusi kedua handler karena memungkinkan banyak event handler. Saya telah membuat kode contoh. Kamu bisa mencobanya

demo

Vikram Rajput
sumber