Cara terbaik untuk menghapus event handler di jQuery?

1053

Saya punya input type="image". Ini bertindak seperti catatan sel di Microsoft Excel. Jika seseorang memasukkan nomor ke dalam kotak teks yang input-imagedipasangkan dengan ini, saya menyiapkan pengendali acara untuk input-image. Kemudian ketika pengguna mengklik image, mereka mendapatkan popup kecil untuk menambahkan beberapa catatan ke data.

Masalah saya adalah bahwa ketika pengguna memasukkan nol ke dalam kotak teks, saya harus menonaktifkan input-imagepengendali acara. Saya sudah mencoba yang berikut, tetapi tidak berhasil.

$('#myimage').click(function { return false; });
Randy L
sumber

Jawaban:

1626

jQuery ≥ 1.7

Dengan jQuery 1.7 dan seterusnya, API peristiwa telah diperbarui, .bind()/ .unbind()masih tersedia untuk kompatibilitas mundur, tetapi metode yang disukai menggunakan fungsi on () / off () . Di bawah ini sekarang akan menjadi,

$('#myimage').click(function() { return false; }); // Adds another click event
$('#myimage').off('click');
$('#myimage').on('click.mynamespace', function() { /* Do stuff */ });
$('#myimage').off('click.mynamespace');

jQuery <1.7

Dalam kode contoh Anda, Anda cukup menambahkan acara klik lain ke gambar, bukan menimpa yang sebelumnya:

$('#myimage').click(function() { return false; }); // Adds another click event

Kedua acara klik kemudian akan dipecat.

Seperti yang dikatakan orang, Anda dapat menggunakan unbind untuk menghapus semua acara klik:

$('#myimage').unbind('click');

Jika Anda ingin menambahkan satu acara dan kemudian menghapusnya (tanpa menghapus acara lain yang mungkin telah ditambahkan) maka Anda dapat menggunakan penempatan nama acara:

$('#myimage').bind('click.mynamespace', function() { /* Do stuff */ });

dan untuk menghapus hanya acara Anda:

$('#myimage').unbind('click.mynamespace');
samjudson
sumber
6
Apakah ada cara untuk menguji apakah unbind()berfungsi? Saya telah menambahkannya dan kedua acara masih berlangsung.
David Yell
19
Nah jika kedua acara masih menyala maka jelas itu tidak berfungsi. Anda harus memberikan lebih banyak info untuk mendapatkan jawaban yang tepat. Coba ajukan pertanyaan terpisah.
samjudson
13
Jawaban lama - juga seperti informasi namespace yang disertakan - tetapi saya lupa; apakah on / off mengembalikan objek jQ? Jika demikian, mungkin jawaban yang lebih lengkap adalah dengan rantai daisy:$('#myimage').off('click').on('click',function(){...})
vol7ron
3
Ya, ya, jika Anda ingin menghapus semua acara klik lainnya dan kemudian menambahkan acara Anda sendiri, Anda bisa melakukan panggilan berantai di atas.
samjudson
Menggunakan .unbind()membantu saya dalam situasi di mana saya mengaktifkan banyak kotak centang, tetapi saya sadar saya menambahkan .click()handler berulang kali, menyebabkan aplikasi hang.
TecBrat
63

Ini tidak tersedia ketika pertanyaan ini dijawab, tetapi Anda juga dapat menggunakan metode live () untuk mengaktifkan / menonaktifkan acara.

$('#myimage:not(.disabled)').live('click', myclickevent);

$('#mydisablebutton').click( function () { $('#myimage').addClass('disabled'); });

Apa yang akan terjadi dengan kode ini adalah ketika Anda mengklik #mydisablebutton, itu akan menambah kelas yang dinonaktifkan pada elemen #myimage. Ini akan membuatnya sehingga pemilih tidak lagi cocok dengan elemen dan acara tidak akan dipecat sampai kelas 'dinonaktifkan' dihapus membuat pemilih .live () valid lagi.

Ini memiliki manfaat lain dengan menambahkan gaya berdasarkan kelas itu juga.

MacAnthony
sumber
3
Cara yang baik untuk digunakan live(), tidak pernah berpikir tentang menggunakannya dengan cara ini sebelumnya ... Selain kenyamanan pengkodean, apakah lebih cepat atau apakah itu menawarkan keuntungan lain untuk menggunakan bind / unbind?
chakrit
2
Jika Anda menambahkan / menghapus elemen, maka ada keuntungan kinerja yang pasti atas pengikatan karena pengikatan dengan live hanya dilakukan sekali. jQuery tampaknya pindah ke lebih banyak acara langsung dan mendelegasikan daripada mengikat ke elemen tertentu.
MacAnthony
3
Untuk menonaktifkan siaran langsung, Anda dapat menggunakan die ()
Moons
9
"Pada jQuery 1.7, metode .live () sudah tidak digunakan lagi. Gunakan .on () untuk melampirkan pengendali acara. Pengguna versi jQuery yang lebih lama harus menggunakan .delegate () sebagai preferensi terhadap .live ()." api.jquery.com/live
Lucas Pottersky
12
Ah, berubah-ubah jQuery, suatu hari kamu membawa 300 perwakilan untuk seorang pria, hari berikutnya itu sudah usang.
MrBoJangles
37

Jika Anda ingin menanggapi suatu peristiwa hanya satu kali , sintaks berikut ini akan sangat membantu:

 $('.myLink').bind('click', function() {
   //do some things

   $(this).unbind('click', arguments.callee); //unbind *just this handler*
 });

Menggunakan arguments.callee , kita dapat memastikan bahwa satu penangan fungsi anonim tertentu dihapus, dan dengan demikian, memiliki penangan waktu tunggal untuk peristiwa tertentu. Semoga ini bisa membantu orang lain.

ghayes
sumber
2
Tentu saja, meskipun kadang-kadang Anda mungkin ingin memiliki logika tertentu tentang kapan handler harus dijilid (mis. Jangan melepas ikatan kecuali mereka mengajukan kotak teks terlebih dahulu).
ghayes
5
arguments.callee dicabut dalam mode ketat!
zloctb
37

Ini dapat dilakukan dengan menggunakan fungsi unbind.

$('#myimage').unbind('click');

Anda bisa menambahkan beberapa penangan acara ke objek dan acara yang sama di jquery. Ini berarti menambahkan yang baru tidak menggantikan yang lama.

Ada beberapa strategi untuk mengubah penangan acara, seperti ruang nama acara. Ada beberapa halaman tentang ini di dokumen online.

Lihatlah pertanyaan ini (begitulah cara saya belajar tentang ikatan). Ada beberapa deskripsi yang berguna dari strategi ini dalam jawaban.

Cara membaca fungsi callback hover terikat di jquery

Mnebuerquo
sumber
32

mungkin metode yang tidak mengikat akan bekerja untuk Anda

$("#myimage").unbind("click");
John Boker
sumber
30

Saya harus mengatur acara ke null menggunakan prop dan attr. Saya tidak bisa melakukannya dengan satu atau yang lain. Saya juga tidak bisa mendapatkan .unbind untuk bekerja. Saya sedang mengerjakan elemen TD.

.prop("onclick", null).attr("onclick", null)
dwhittenburg
sumber
1
Saya memilih ini karena saya telah mencoba untuk melepaskan ikatan pada blur sekitar 30 mintues. '.unbind' tidak bekerja, '.prop' tidak bekerja, '.attr' tidak berfungsi, tetapi trik ini dengan keduanya .prop dan .attr bersama-sama melakukan trik. aneh. Saya menggunakan Chrome dengan jquery 1.7.2
Jeremy
Sama disini! saya mencoba menghapus acara klik dari tag <a> yang sederhana! Terima kasih untuk ini. Dalam kasus saya .prop ("onclick", null) sudah cukup.
Jan Lobau
sama disini. tidak mengikat dan mematikan tidak bekerja untuk saya pada FF dengan jq 1.7.2 dan .prop ("onclick", null) juga cukup dalam kasus saya
bryanallott
4
Saya pikir alasan metode di atas tidak berhasil untuk kalian adalah karena cara Anda mengaturnya. Jika Anda menulis event handler ke DOM maka ya, menghapus atribut ini diperlukan untuk menghapus event handler, namun, saya pikir sebagian besar orang (termasuk saya) ingin menyimpan hal-hal seperti itu (javascrip, event handler, dll.) Dari DOM, jadi ketika kita ingin mengatur event handler kita menggunakan sesuatu seperti $("#elementId").click(function(){//Event execution code goes here});sehingga tidak ada di halaman html sama sekali. Untuk menghapus bahwa kita sebenarnya perlu menggunakan .unbind(), atau yang disukai.off()
VoidKing
Berikut ini seperti dari seseorang yang baru saja menghabiskan satu jam untuk menemukan bahwa properti yang ditambahkan melalui jQuery tidak muncul di panel elemen Chrome. Sudah mencoba unbinddan offdan itu tidak menyelesaikan masalah. Terima kasih banyak!
Renan
13

Jika acara dilampirkan dengan cara ini , dan target tidak terikat:

$('#container').on('click','span',function(eo){
    alert(1);

    $(this).off(); //seams easy, but does not work

    $('#container').off('click','span'); //clears click event for every span

    $(this).on("click",function(){return false;}); //this works.

});​

sumber
11

Anda mungkin menambahkan onclickpenangan sebagai marka sebaris:

<input id="addreport" type="button" value="Add New Report" onclick="openAdd()" />

Jika demikian, jquery .off()atau .unbind()tidak akan berfungsi. Anda perlu menambahkan event handler asli di jquery juga:

$("#addreport").on("click", "", function (e) {
   openAdd();
});

Kemudian jquery memiliki referensi ke pengendali event dan dapat menghapusnya:

$("#addreport").off("click")

VoidKing menyebutkan ini sedikit lebih miring dalam komentar di atas.

davaus
sumber
9

Diperbarui untuk 2014

Menggunakan versi terbaru jQuery, Anda sekarang dapat melepaskan ikatan semua peristiwa di namespace hanya dengan melakukan $( "#foo" ).off( ".myNamespace" );

alexpls
sumber
8

Cara terbaik untuk menghapus acara onclick inline adalah $(element).prop('onclick', null);

Shahrukh Azeem
sumber
8

Bagi remove SEMUA event-handlers , inilah yang berhasil bagi saya:

Untuk menghapus semua penangan acara berarti memiliki dataran HTML structuretanpa semua yang event handlersmelekat pada elementdan child nodes. Untuk melakukan ini, jQuery's clone()membantu.

var original, clone;
// element with id my-div and its child nodes have some event-handlers
original = $('#my-div');
clone = original.clone();
//
original.replaceWith(clone);

Dengan ini, kita akan memiliki clonedi tempat originaltanpa event-handlersdi atasnya.

Semoga berhasil...

Akash
sumber
7

Terima kasih untuk informasi. sangat membantu saya menggunakannya untuk mengunci interaksi halaman saat dalam mode edit oleh pengguna lain. Saya menggunakannya bersamaan dengan ajaxComplete. Tidak perlu perilaku yang sama tetapi agak mirip.

function userPageLock(){
    $("body").bind("ajaxComplete.lockpage", function(){
        $("body").unbind("ajaxComplete.lockpage");
        executePageLock();      
    });
};  

function executePageLock(){
    //do something
}
jquery_user
sumber
5

.on()Metode dalam kasus sebelumnya digunakan dengan pemilih tertentu, seperti dalam contoh berikut:

$('body').on('click', '.dynamicTarget', function () {
    // Code goes here
});

Keduanya unbind()dan .off()metode tidak akan berhasil.

Namun, metode .undelegate () dapat digunakan untuk sepenuhnya menghapus handler dari acara untuk semua elemen yang cocok dengan pemilih saat ini:

$("body").undelegate(".dynamicTarget", "click")
Ilia Rostovtsev
sumber
1
Saya menggulir seluruh halaman sambil mencari solusi ini, bekerja seperti pesona.
Abhishek Pandey
4

Jika Anda menggunakan $(document).on()untuk menambahkan pendengar ke elemen yang dibuat secara dinamis maka Anda mungkin harus menggunakan yang berikut untuk menghapusnya:

// add the listener
$(document).on('click','.element',function(){
    // stuff
});

// remove the listener
$(document).off("click", ".element");
ow3n
sumber
2

jika Anda mengatur onclickvia htmlAnda perluremoveAttr ($(this).removeAttr('onclick'))

jika Anda mengaturnya melalui jquery (seperti setelah klik pertama dalam contoh saya di atas) maka Anda perlu melakukannya unbind($(this).unbind('click'))

Ishan Liyanage
sumber
2

Saya tahu ini terlambat, tapi mengapa tidak menggunakan JS biasa untuk menghapus acara?

var myElement = document.getElementById("your_ID");
myElement.onclick = null;

atau, jika Anda menggunakan fungsi bernama sebagai pengendali event:

function eh(event){...}
var myElement = document.getElementById("your_ID");
myElement.addEventListener("click",eh); // add event handler
myElement.removeEventListener("click",eh); //remove it
Silviu Preda
sumber
Saran bagus, saya lebih suka menggunakan javascript asli saat tersedia
Michiel
1

Semua pendekatan yang dijelaskan tidak bekerja untuk saya karena saya menambahkan acara klik on()ke dokumen tempat elemen dibuat saat run-time:

$(document).on("click", ".button", function() {
    doSomething();
});


Solusi saya:

Karena saya tidak dapat melepaskan ikatan kelas ".button", saya hanya menetapkan kelas lain pada tombol yang memiliki gaya CSS yang sama. Dengan melakukan hal itu, live / on-event-handler akhirnya mengabaikan klik:

// prevent another click on the button by assigning another class
$(".button").attr("class","buttonOff");

Semoga itu bisa membantu.

Kai Noack
sumber
1

Semoga kode saya di bawah ini menjelaskan semuanya. HTML:

(function($){

     $("#btn_add").on("click",function(){
       $("#btn_click").on("click",added_handler);
       alert("Added new handler to button 1");
     });

  
 
     $("#btn_remove").on("click",function(){
       $("#btn_click").off("click",added_handler);
       alert("Removed new handler to button 1");
     });

  
   function fixed_handler(){
    alert("Fixed handler");
  }
  
   function added_handler(){
    alert("new handler");
  }
  
  $("#btn_click").on("click",fixed_handler);
  $("#btn_fixed").on("click",fixed_handler);
  
  
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btn_click">Button 1</button>
  <button id="btn_add">Add Handler</button>
  <button id="btn_remove">Remove Handler</button>
  <button id="btn_fixed">Fixed Handler</button>

mistik
sumber
1
mengapa Anda masuk })(jQuery);ke IIFE ketika sudah dapat diakses secara global?
Bryan P
2
Pertanyaan bagus, Bryan. Metode ini telah dimasukkan dalam gen saya karena latihan. - Mungkin ada beberapa kemungkinan plugin non jquery untuk memiliki variabel $, maka saya tidak dapat menggunakan $ secara langsung. - Sering menggunakan kata "jQuery" dalam file skrip js dapat meningkatkan ukuran byte file, di mana jQuery adalah string 6 byte. Karenanya saya lebih suka menggunakan "$" atau variabel byte tunggal.
mysticmo
0

Cukup hapus saja dari tombol:

$('.classname').click(function(){
$( ".classname" ).remove();
});
Mitra
sumber