javascript - masalah hidup dan mati mengikat acara jQuery
迷茫
迷茫 2017-05-18 10:51:00
0
3
548

Kod adalah seperti berikut:

var $test = $(document);
  
function handler1() {
  console.log( "handler1" );
  $test.off( "click", handler2 );
}
  
function handler2() {
  console.log( "handler2" );
}
  
$test.on( "click", handler1 );
$test.on( "click", handler2 );

Mengapa kod ini mengeluarkan pengendali1 dan pengendali2 apabila ia diklik buat kali pertama?
Rujuk dokumentasi jQuery

Penjelasan dalam dokumen ialah: Menambah atau mengalih keluar pengendali acara pada elemen semasa tidak akan berkuat kuasa sehingga kali seterusnya acara dikendalikan
Mungkin bahasa Inggeris saya terlalu teruk, saya rasa ungkapan di tempat ini tidak begitu tepat , ia sepatutnya Penambahan atau pemadaman acara yang sama adalah tidak sah semasa pemprosesan semasa Sebagai contoh, saya menukar dua klik kepada yang berikut

var $test = $(document);
  
function handler1() {
  console.log( "handler1" );
  $test.off( "mouseup", handler2 );
}
  
function handler2() {
  console.log( "handler2" );
}
  
$test.on( "mousedown", handler1 );
$test.on( "mouseup", handler2 );

Kemudian hanya pengendali1 akan dikeluarkan. Ia dapat dilihat bahawa mematikan tetikus dalam mousedown adalah berjaya

Kembali kepada permulaan, mengapa penambahan atau pemadaman acara yang sama tidak sah semasa pemprosesan semasa? (Saya cuba mencari kod sumber jQuery, tetapi ia agak rumit, jadi saya berputus asa)

迷茫
迷茫

业精于勤,荒于嬉;行成于思,毁于随。

membalas semua(3)
左手右手慢动作

Masih perlu bermula dari kod sumber

Lihat di sini dahulu: https://github.com/jquery/jqu...

handlerQueue = jQuery.event.handlers.call( this, event, handlers );

Ini adalah permulaan kod teras untuk pengedaran acara Dapat dilihat bahawa jquery perlu memanggil this.event.handler apabila mengedarkan acara untuk mencari senarai panggilan balik acara Di sini handlerQueue hanyalah sebahagian daripada senarai acara dalaman Salin, dan perkara yang anda gunakan untuk menukar ialah senarai acara dalaman, yang secara semula jadi tidak mempunyai kesan pada handlerQueue yang disalin.

Ia seperti semua fungsi panggil balik acara disimpan dalam periuk Apabila peristiwa berlaku, jquery akan menyalin panggilan balik, memasukkannya ke dalam mangkuk, dan kemudian melaksanakan fungsi dalam mangkuk mengikut urutan. Perkara yang anda ubah secara off hanyalah fungsi dalam periuk, dan fungsi dalam mangkuk tidak terjejas.

左手右手慢动作

Anda boleh menganggap on sebagai menambah kaedah pemprosesan pada tatasusunan pemprosesan acara komponen, dan mematikan sebagai mengalih keluar kaedah ini daripada tatasusunan. Apabila peristiwa dicetuskan, jq akan melaksanakan kaedah dalam tatasusunan pemprosesan acara sekaligus. Jadi apakah yang akan berlaku jika mati dipanggil dalam kaedah pemprosesan acara? Dokumen itu telah menyatakan dengan sangat jelas bahawa kaedah pemprosesan tidak akan dialih keluar daripada tatasusunan serta-merta dalam gelung pencetus peristiwa semasa Ia hanya akan ditunjukkan apabila peristiwa terikat dicetuskan semula.

Peter_Zhu

Terima kasih semua
Masalahnya telah ditemui Sebabnya ialah apabila jq merangkum peristiwa secara dalaman, peristiwa jenis yang sama akan ditambahkan pada tatasusunan yang sama, dan apabila peristiwa itu dicetuskan, traversal adalah. salinan tatasusunan ini , off tidak mengubah tatasusunan yang disalin, jadi hanler2 adalah output pada klik pertama dan tetikus turun, kerana ia adalah jenis acara yang berbeza, ia dikapsulkan kepada dua tatasusunan, jadi ia berkesan untuk. off mouseup dalam mousedown of. Mungkin ungkapan itu tidak begitu baik, sila siarkan beberapa baris kod sumber jq utama

//获取触发的事件的数组,在上面的代码中触发click时这个数组中是有两个值的,而触发mousedown时是只有一个值的,这个值是内部封装的一个handleObj对象
handlers = ((jQuery._data(this, "events") || {})[event.type] || [])

...

//之后会把这个handlers数组根据是否委托来slice(也是这个地方复制了handlers,导致click中的off第一次点击的时候无效),然后添加到数组handlerQueue中
handlerQueue.push({ elem: this, matches: handlers.slice(delegateCount) })

...
//最后触发的时候是遍历handlerQueue中的matches来执行
 for (i = 0; i < handlerQueue.length && !event.isPropagationStopped() ; i++) {
                matched = handlerQueue[i];
                event.currentTarget = matched.elem;

                for (j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped() ; j++) {
                    ...
                    }
}
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan