Rumah  >  Soal Jawab  >  teks badan

javascript - masalah hidup dan mati mengikat acara jQuery

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)

迷茫迷茫2684 hari yang lalu497

membalas semua(3)saya akan balas

  • ringa_lee

    ringa_lee2017-05-18 10:53:00

    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.

    balas
    0
  • ringa_lee

    ringa_lee2017-05-18 10:53:00

    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.

    balas
    0
  • 天蓬老师

    天蓬老师2017-05-18 10:53:00

    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++) {
                        ...
                        }
    }

    balas
    0
  • Batalbalas