Cách tốt nhất để loại bỏ một trình xử lý sự kiện trong jQuery?


1053

Tôi có một input type="image". Điều này hoạt động như các ghi chú di động trong Microsoft Excel. Nếu ai đó nhập một số vào hộp văn bản mà input-imagecặp này được ghép với, tôi sẽ thiết lập trình xử lý sự kiện cho input-image. Sau đó, khi người dùng nhấp vào image, họ sẽ nhận được một cửa sổ bật lên để thêm một số ghi chú vào dữ liệu.

Vấn đề của tôi là khi người dùng nhập số 0 vào hộp văn bản, tôi cần phải tắt input-imagetrình xử lý sự kiện. Tôi đã thử những điều sau đây, nhưng vô ích.

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

Câu trả lời:


1626

jQuery ≥ 1.7

Với jQuery 1.7 trở đi, API sự kiện đã được cập nhật, .bind()/ .unbind()vẫn có sẵn để tương thích ngược, nhưng phương thức ưa thích là sử dụng các hàm on () / off () . Dưới đây sẽ là,

$('#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

Trong mã ví dụ của bạn, bạn chỉ cần thêm một sự kiện nhấp chuột khác vào hình ảnh, không ghi đè lên sự kiện trước đó:

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

Cả hai sự kiện nhấp chuột sau đó sẽ bị sa thải.

Như mọi người đã nói, bạn có thể sử dụng unbind để xóa tất cả các sự kiện nhấp chuột:

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

Nếu bạn muốn thêm một sự kiện và sau đó xóa nó (mà không xóa bất kỳ sự kiện nào khác có thể đã được thêm vào) thì bạn có thể sử dụng không gian tên sự kiện:

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

và chỉ xóa sự kiện của bạn:

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

6
Có cách nào để kiểm tra nếu unbind()đang làm việc? Tôi đã thêm nó và cả hai sự kiện vẫn đang diễn ra.
David Yell

19
Chà nếu cả hai sự kiện vẫn đang nổ súng thì rõ ràng nó không hoạt động. Bạn sẽ phải cung cấp thêm thông tin để có câu trả lời thích hợp. Hãy thử hỏi một câu hỏi riêng biệt.
samjudson

13
Câu trả lời cũ - cũng giống như thông tin không gian tên được bao gồm - nhưng tôi quên mất; bật / tắt trả về đối tượng jQ? Nếu vậy, có lẽ một câu trả lời đầy đủ hơn sẽ là chuỗi cúc:$('#myimage').off('click').on('click',function(){...})
vol7ron

3
Có, họ làm như vậy, vâng, nếu bạn muốn xóa tất cả các sự kiện nhấp chuột khác và sau đó thêm sự kiện của riêng bạn, bạn có thể thực hiện cuộc gọi được xâu chuỗi ở trên.
samjudson

Việc sử dụng .unbind()đã giúp tôi trong tình huống tôi đang bật một loạt các hộp kiểm, nhưng tôi đã liên tục thêm lại .click()trình xử lý, khiến ứng dụng bị treo.
TecBrat

63

Điều này không khả dụng khi câu hỏi này đã được trả lời, nhưng bạn cũng có thể sử dụng phương thức live () để bật / tắt các sự kiện.

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

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

Điều gì sẽ xảy ra với mã này là khi bạn nhấp vào #mydisablebutton, nó sẽ thêm lớp bị vô hiệu hóa vào phần tử #myimage. Điều này sẽ làm cho nó để bộ chọn không còn phù hợp với phần tử và sự kiện sẽ không được kích hoạt cho đến khi lớp 'bị vô hiệu hóa được loại bỏ làm cho bộ chọn .live () trở lại hợp lệ.

Điều này có lợi ích khác bằng cách thêm kiểu dáng dựa trên lớp đó là tốt.


3
Cách sử dụng tuyệt vời live(), chưa bao giờ nghĩ đến việc sử dụng nó theo cách này trước đây ... Ngoài sự tiện lợi về mã hóa, nó có nhanh hơn hay nó cung cấp bất kỳ lợi thế nào khác khi sử dụng bind / unbind?
chakrit

2
Nếu bạn đang thêm / xóa các phần tử, thì có những lợi thế về hiệu suất nhất định so với liên kết vì liên kết với trực tiếp chỉ được thực hiện một lần. jQuery dường như đang chuyển sang các sự kiện trực tiếp và ủy thác hơn là ràng buộc với các yếu tố cụ thể.
MacAnthony

3
Để tắt trực tiếp, bạn có thể sử dụng die ()
Moons

9
"Kể từ jQuery 1.7, phương thức .live () không được dùng nữa. Sử dụng .on () để đính kèm các trình xử lý sự kiện. Người dùng các phiên bản cũ hơn của jQuery nên sử dụng .delegate () để ưu tiên cho .live ()." api.jquery.com/live
Lucas Pottersky

12
Ah, hay thay đổi jQuery, một ngày bạn mang 300 rep cho một anh chàng, ngày hôm sau nó đã lỗi thời.
MrBoJangles

37

Nếu bạn muốn trả lời một sự kiện chỉ một lần , cú pháp sau đây sẽ thực sự hữu ích:

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

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

Sử dụng argument.callee , chúng tôi có thể đảm bảo rằng một trình xử lý hàm ẩn danh cụ thể được loại bỏ và do đó, có một trình xử lý thời gian duy nhất cho một sự kiện nhất định. Hy vọng điều này sẽ giúp những người khác.


2
Hoàn toàn, mặc dù đôi khi bạn có thể muốn có logic nhất định về thời điểm trình xử lý không bị ràng buộc (ví dụ: không hủy liên kết trừ khi họ gửi ra một hộp văn bản trước).
ghayes

5
argument.callee bị tước quyền trong chế độ nghiêm ngặt!
zloctb

37

Điều này có thể được thực hiện bằng cách sử dụng chức năng unbind.

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

Bạn có thể thêm nhiều trình xử lý sự kiện vào cùng một đối tượng và sự kiện trong jquery. Điều này có nghĩa là thêm một cái mới không thay thế cái cũ.

Có một số chiến lược để thay đổi trình xử lý sự kiện, chẳng hạn như không gian tên sự kiện. Có một số trang về điều này trong các tài liệu trực tuyến.

Nhìn vào câu hỏi này (đó là cách tôi học được về unbind). Có một số mô tả hữu ích về các chiến lược này trong các câu trả lời.

Làm thế nào để đọc các hàm gọi lại di chuột bị ràng buộc trong jquery


32

có lẽ phương pháp unbind sẽ làm việc cho bạn

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

30

Tôi đã phải đặt sự kiện thành null bằng cách sử dụng prop và attr. Tôi không thể làm điều đó với cái này hay cái khác. Tôi cũng không thể làm cho .unbind hoạt động. Tôi đang làm việc trên một yếu tố TD.

.prop("onclick", null).attr("onclick", null)

1
Tôi đã bỏ phiếu này vì tôi đã cố gắng hủy liên kết một khoảng 30 phút. '.unbind' không hoạt động, '.prop' không hoạt động, '.attr' không hoạt động, nhưng thủ thuật này với cả .prop và .attr cùng thực hiện thủ thuật. lẻ Tôi đang sử dụng Chrome với jquery 1.7.2
Jeremy

Tương tự ở đây! tôi đã cố xóa sự kiện nhấp chuột khỏi thẻ <a> đơn giản! Thanx cho điều này. Trong trường hợp của tôi .prop ("onclick", null) là đủ.
Jan lobau

tương tự ở đây hủy kết nối và tắt không hoạt động với tôi trên FF với jq 1.7.2 và .prop ("onclick", null) cũng đủ trong trường hợp của tôi
bryanallott

4
Tôi nghĩ lý do các phương pháp trên không hiệu quả với các bạn là vì cách bạn thiết lập nó. Tuy nhiên, nếu bạn đã viết trình xử lý sự kiện vào DOM thì có, việc xóa thuộc tính này là cần thiết để xóa trình xử lý sự kiện, tuy nhiên, tôi nghĩ rằng hầu hết mọi người (bao gồm cả bản thân tôi) muốn loại bỏ những thứ đó (javascrip, xử lý sự kiện, v.v.) DOM, vì vậy khi chúng tôi muốn thiết lập một trình xử lý sự kiện, chúng tôi sử dụng một cái gì đó giống như $("#elementId").click(function(){//Event execution code goes here});vậy để nó hoàn toàn không có trong trang html. Để xóa rằng chúng tôi thực sự cần sử dụng .unbind()hoặc ưu tiên.off()
VoidKing

Đây giống như một người vừa dành một giờ để khám phá các thuộc tính được thêm thông qua jQuery không hiển thị trên bảng thành phần của Chrome. Đã cố gắng unbindoffnó đã không giải quyết vấn đề. Cảm ơn rât nhiều!
Renan

13

Nếu sự kiện được đính kèm theo cách này và mục tiêu sẽ không bị chặn:

$('#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.

});​

11

Bạn có thể thêm onclicktrình xử lý dưới dạng đánh dấu nội tuyến:

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

Nếu vậy, jquery .off()hoặc .unbind()sẽ không hoạt động. Bạn cũng cần thêm trình xử lý sự kiện gốc trong jquery:

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

Sau đó, jquery có một tham chiếu đến trình xử lý sự kiện và có thể loại bỏ nó:

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

VoidKing đề cập đến điều này một chút xiên trong một bình luận ở trên.


9

Cập nhật cho năm 2014

Sử dụng phiên bản mới nhất của jQuery, giờ đây bạn có thể hủy liên kết tất cả các sự kiện trên một không gian tên bằng cách thực hiện đơn giản $( "#foo" ).off( ".myNamespace" );


8

Cách tốt nhất để loại bỏ sự kiện onclick nội tuyến là $(element).prop('onclick', null);


8

Đối với remove TẤT CẢ event-handlers , đây là những gì làm việc cho tôi:

Để loại bỏ tất cả các sự kiện xử lý có nghĩa là phải có đơn giản HTML structurekhông có tất cả các event handlersthuộc elementvà nó child nodes. Để làm điều này, jQuery's clone()đã giúp.

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);

Với điều này, chúng tôi sẽ có clonevị trí originalkhông có event-handlerstrên đó.

Chúc may mắn...


7

Cảm ơn vì thông tin. rất hữu ích tôi đã sử dụng nó để khóa tương tác trang trong khi ở chế độ chỉnh sửa bởi người dùng khác. Tôi đã sử dụng nó kết hợp với ajaxComplete. Không phải hành vi giống nhau nhưng hơi giống nhau.

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

function executePageLock(){
    //do something
}

5

Trong trường hợp .on()phương pháp trước đây được sử dụng với bộ chọn cụ thể, như trong ví dụ sau:

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

Cả hai unbind().off()phương pháp sẽ không làm việc.

Tuy nhiên, phương thức .undelegate () có thể được sử dụng để loại bỏ hoàn toàn trình xử lý khỏi sự kiện cho tất cả các phần tử khớp với bộ chọn hiện tại:

$("body").undelegate(".dynamicTarget", "click")

1
Tôi cuộn toàn bộ trang trong khi tìm kiếm giải pháp này, làm việc như một cơ duyên.
Abhishek Pandey

4

Nếu bạn sử dụng $(document).on()để thêm một trình lắng nghe vào một phần tử được tạo động thì bạn có thể phải sử dụng các phần sau để loại bỏ nó:

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

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


2

nếu bạn đặt onclickthông quahtml bạn cần phảiremoveAttr ($(this).removeAttr('onclick'))

nếu bạn đặt nó qua jquery (như lần nhấp đầu tiên trong ví dụ của tôi ở trên) thì bạn cần phải unbind($(this).unbind('click'))


2

Tôi biết điều này đến muộn, nhưng tại sao không sử dụng JS đơn giản để loại bỏ sự kiện này?

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

hoặc, nếu bạn sử dụng chức năng được đặt tên làm trình xử lý sự kiện:

function eh(event){...}
var myElement = document.getElementById("your_ID");
myElement.addEventListener("click",eh); // add event handler
myElement.removeEventListener("click",eh); //remove it

Đề xuất tốt, tôi thích sử dụng javascript gốc khi có sẵn
Michiel

1

Tất cả các cách tiếp cận được mô tả không hoạt động đối với tôi vì tôi đã thêm sự kiện nhấp vào on()tài liệu nơi phần tử được tạo vào thời gian chạy:

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


Cách giải quyết của tôi:

Vì tôi không thể hủy liên kết lớp ".button", tôi chỉ gán một lớp khác cho nút có cùng kiểu CSS. Bằng cách làm như vậy, trình xử lý trực tiếp / sự kiện đã bỏ qua lần nhấp cuối cùng:

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

Mong rằng sẽ giúp.


1

Hy vọng mã dưới đây của tôi giải thích tất cả. 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>


1
Tại sao bạn chuyển })(jQuery);vào IIFE khi nó có thể được truy cập trên toàn cầu?
Bryan P

2
Câu hỏi hay Bryan. Phương pháp này đã được nhập vào gen của tôi do thực hành. - Có thể có một số khả năng để plugin không jquery có biến $, do đó tôi không thể sử dụng $ trực tiếp. - Việc sử dụng thường xuyên từ "jQuery" trong tệp tập lệnh js có thể tăng kích thước byte của tệp, trong đó jQuery là chuỗi 6 byte. Do đó tôi thích sử dụng "$" hoặc bất kỳ biến nào của byte đơn.
mysticmo

0

Chỉ cần loại bỏ nó khỏi nút:

$('.classname').click(function(){
$( ".classname" ).remove();
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.