วิธีที่ดีที่สุดในการลบตัวจัดการเหตุการณ์ใน jQuery?


1053

input type="image"ฉันมี สิ่งนี้ทำหน้าที่เหมือนกับบันทึกย่อของเซลล์ใน Microsoft Excel ถ้ามีคนเข้ามาตัวเลขลงในกล่องข้อความที่ว่านี้อยู่คู่กับการติดตั้งผมดำเนินกิจกรรมสำหรับinput-image input-imageจากนั้นเมื่อผู้ใช้คลิกที่imageพวกเขาจะได้รับป๊อปอัพเล็กน้อยเพื่อเพิ่มบันทึกลงในข้อมูล

ปัญหาของฉันคือเมื่อผู้ใช้ป้อนค่าศูนย์ลงในกล่องข้อความฉันต้องปิดการใช้งานinput-imageตัวจัดการเหตุการณ์ ฉันได้ลองสิ่งต่อไปนี้แล้ว แต่ก็ไม่มีประโยชน์

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

คำตอบ:


1626

jQuery ≥ 1.7

กับ jQuery 1.7 เป็นต้นไปเหตุการณ์ API ที่ได้รับการปรับปรุง.bind()/ .unbind()ยังคงมีอยู่สำหรับการทำงานร่วมกันหลัง แต่วิธีการที่ต้องการคือการใช้ใน () / ปิด ()ฟังก์ชั่น ด้านล่างจะเป็น

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

ในโค้ดตัวอย่างของคุณคุณเพียงแค่เพิ่มเหตุการณ์การคลิกอีกครั้งลงในภาพไม่ใช่การแทนที่เหตุการณ์ก่อนหน้า:

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

เหตุการณ์การคลิกทั้งสองจะถูกไล่ออก

อย่างที่คนอื่นพูดไว้คุณสามารถใช้ unbind เพื่อลบกิจกรรมคลิกทั้งหมด:

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

หากคุณต้องการเพิ่มเหตุการณ์เดียวแล้วลบออก (โดยไม่ลบกิจกรรมอื่น ๆ ที่อาจถูกเพิ่ม) จากนั้นคุณสามารถใช้การกำหนดเนมสเปซได้:

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

และเพื่อลบเฉพาะกิจกรรมของคุณ:

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

6
มีวิธีทดสอบว่าunbind()ทำงานหรือไม่ ฉันได้เพิ่มแล้วและทั้งสองเหตุการณ์ยังคงมีการยิง
David Yell

19
ถ้าเหตุการณ์ทั้งสองยังคงมีการยิงก็ชัดเจนว่ามันไม่ทำงาน คุณต้องให้ข้อมูลเพิ่มเติมเพื่อรับคำตอบที่ถูกต้อง ลองถามคำถามแยกต่างหาก
samjudson

13
คำตอบเก่า - เช่นเดียวกับข้อมูล namespace รวม - แต่ฉันลืม; เปิด / ปิดจะส่งคืนวัตถุ jQ หรือไม่ ถ้าเป็นเช่นนั้นอาจเป็นคำตอบที่สมบูรณ์ยิ่งขึ้นคือโซ่ดอกเดซี:$('#myimage').off('click').on('click',function(){...})
77

3
ใช่พวกเขาทำดังนั้นใช่ถ้าคุณต้องการล้างกิจกรรมการคลิกอื่น ๆ ทั้งหมดแล้วเพิ่มของคุณเองคุณสามารถทำสายที่ถูกล่ามโซ่ข้างต้น
samjudson

การใช้.unbind()ช่วยฉันในสถานการณ์ที่ฉันสลับช่องทำเครื่องหมายหลายช่อง แต่ทำให้ฉันใช้.click()ตัวจัดการซ้ำได้อีกครั้งทำให้แอปหยุดทำงาน
TecBrat

63

สิ่งนี้ไม่สามารถใช้ได้เมื่อตอบคำถามนี้ แต่คุณยังสามารถใช้วิธีlive ()เพื่อเปิด / ปิดการใช้งานกิจกรรมได้

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

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

สิ่งที่จะเกิดขึ้นกับรหัสนี้คือเมื่อคุณคลิก #mydisablebutton มันจะเพิ่มคลาสที่ปิดใช้งานองค์ประกอบ #myimage สิ่งนี้จะทำให้มันเพื่อให้ตัวเลือกไม่ตรงกับองค์ประกอบและเหตุการณ์จะไม่ถูกไล่ออกจนกว่าคลาส 'ปิดการใช้งาน' จะถูกลบออกทำให้ตัวเลือก. live () ใช้ได้อีกครั้ง

สิ่งนี้มีประโยชน์อื่น ๆ โดยการเพิ่มสไตล์ตามคลาสนั้นด้วย


3
วิธีที่ดีในการใช้งานlive()ไม่เคยคิดที่จะใช้วิธีนี้มาก่อน ... นอกเหนือจากความสะดวกในการเขียนโค้ดมันเร็วกว่าหรือไม่หรือมีข้อได้เปรียบอื่น ๆ ในการใช้ bind / unbind
chakrit

2
หากคุณกำลังเพิ่ม / ลบองค์ประกอบแสดงว่ามีข้อได้เปรียบด้านประสิทธิภาพที่ชัดเจนกว่าการเชื่อมโยงเนื่องจากการเชื่อมโยงกับการถ่ายทอดสดทำได้เพียงครั้งเดียวเท่านั้น ดูเหมือนว่า jQuery จะย้ายไปยังกิจกรรมสดและมอบหมายมากกว่าการผูกกับองค์ประกอบเฉพาะ
MacAnthony

3
หากต้องการปิดการใช้งานสดคุณสามารถใช้ die ()
Moons

9
"ตั้งแต่ jQuery 1.7 เมธอด. live () เลิกใช้ใช้. on () เพื่อแนบตัวจัดการเหตุการณ์ผู้ใช้ jQuery เวอร์ชันเก่าควรใช้. delegate () ในการตั้งค่า. live ()" api.jquery.com/live
Lucas Pottersky

12
อา, ไม่แน่นอน jQuery, วันหนึ่งคุณนำตัวแทน 300 คนมาให้ผู้ชาย, ในวันถัดไปมันล้าสมัย
MrBoJangles

37

หากคุณต้องการตอบกลับเหตุการณ์เพียงครั้งเดียวไวยากรณ์ต่อไปนี้ควรเป็นประโยชน์จริง ๆ :

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

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

การใช้arguments.calleeเราสามารถตรวจสอบให้แน่ใจว่าตัวจัดการแบบไม่ระบุชื่อฟังก์ชั่นเฉพาะหนึ่งตัวถูกลบออกดังนั้นจึงมีตัวจัดการเวลาเดียวสำหรับเหตุการณ์ที่กำหนด หวังว่านี่จะช่วยผู้อื่น


2
อย่างแน่นอนแม้ว่าบางครั้งคุณอาจต้องการมีเหตุผลบางอย่างเกี่ยวกับเวลาที่ตัวจัดการควรถูกยกเลิกการเชื่อม (เช่นอย่าแยกเว้นแต่ว่าพวกเขายื่นกล่องข้อความออกมาก่อน)
ghayes

5
arguments.callee ถูกควบคุมในโหมดเข้มงวด!
zloctb

37

สิ่งนี้สามารถทำได้โดยใช้ฟังก์ชัน unbind

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

คุณสามารถเพิ่มตัวจัดการเหตุการณ์หลายตัวให้กับวัตถุและเหตุการณ์เดียวกันด้วย jquery หมายความว่าการเพิ่มอันใหม่ไม่ได้เป็นการแทนที่อันใหม่

มีกลยุทธ์หลายอย่างสำหรับการเปลี่ยนตัวจัดการเหตุการณ์เช่นเนมสเปซเหตุการณ์ มีบางหน้าเกี่ยวกับเรื่องนี้ในเอกสารออนไลน์

ดูคำถามนี้ (นั่นเป็นวิธีที่ฉันเรียนรู้ที่จะผูกมัด) มีคำอธิบายที่เป็นประโยชน์ของกลยุทธ์เหล่านี้ในคำตอบ

วิธีการอ่านฟังก์ชั่นโฮเวอร์โทรกลับที่ถูกผูกไว้ใน jquery



30

ฉันต้องตั้งค่าเหตุการณ์เป็นโมฆะโดยใช้เสาและ attr ฉันไม่สามารถทำได้ด้วยอย่างใดอย่างหนึ่ง ฉันยังไม่ได้รับ. ผูกการทำงาน ฉันกำลังทำงานกับองค์ประกอบ TD

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

1
ฉันโหวตเรื่องนี้ขึ้นมาเพราะฉันพยายามที่จะปลดการผูกมัดสีเบลอประมาณ 30 นาที '.unbind' ไม่ทำงาน '.prop' ไม่ทำงาน '.attr' ไม่ทำงาน แต่เคล็ดลับนี้กับ. prop และ .attr ทั้งสองเข้าด้วยกันทำเคล็ดลับ แปลก ฉันใช้ Chrome กับ jQuery 1.7.2
Jeremy

กันที่นี่! ฉันพยายามลบกิจกรรมคลิกจากแท็ก <a> ง่าย ๆ ! ขอบคุณสำหรับสิ่งนี้ ในกรณีของฉัน .prop ("onclick", null) ก็เพียงพอแล้ว
Jan Lobau

กันที่นี่ แยกออกและปิดไม่ทำงานสำหรับฉันที่ FF ด้วย jq 1.7.2 และ. prop ("onclick", null) ก็เพียงพอแล้วในกรณีของฉัน
bryanallott

4
ฉันคิดว่าเหตุผลที่วิธีการข้างต้นไม่ได้ผลกับคุณเพราะคุณตั้งค่ามันอย่างไร หากคุณเขียนตัวจัดการเหตุการณ์ลงใน DOM แล้วใช่การล้างแอตทริบิวต์นี้จำเป็นต่อการล้างตัวจัดการเหตุการณ์อย่างไรก็ตามฉันคิดว่าคนส่วนใหญ่ (รวมถึงตัวเอง) ต้องการเก็บสิ่งต่าง ๆ (javascrip ตัวจัดการเหตุการณ์ ฯลฯ ) ออกจาก DOM ดังนั้นเมื่อเราต้องการตั้งค่าตัวจัดการเหตุการณ์เราใช้สิ่งที่ต้องการ$("#elementId").click(function(){//Event execution code goes here});เพื่อไม่ให้อยู่ในหน้า html เลย เพื่อให้ชัดเจนว่าเราจำเป็นต้องใช้จริง.unbind()หรือสิ่งที่ต้องการ.off()
VoidKing

นี่คือสิ่งที่คล้ายกับคนที่เพิ่งใช้เวลาหนึ่งชั่วโมงเพื่อค้นหาว่าคุณสมบัติที่เพิ่มผ่าน jQuery ไม่แสดงในแผงองค์ประกอบของ Chrome เคยลองunbindแล้วoffและมันก็ไม่ได้แก้ปัญหา ขอบคุณมาก!
Renan

13

หากมีการแนบเหตุการณ์ด้วยวิธีนี้และเป้าหมายต้องไม่เชื่อมต่อ:

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

คุณอาจเพิ่มonclickตัวจัดการเป็นมาร์กอัปแบบอินไลน์:

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

ถ้าเป็นเช่นนั้น jquery .off()หรือ.unbind()จะไม่ทำงาน คุณต้องเพิ่มตัวจัดการเหตุการณ์ดั้งเดิมใน jquery ด้วย:

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

จากนั้น jquery มีการอ้างอิงไปยังตัวจัดการเหตุการณ์และสามารถลบได้:

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

VoidKing กล่าวถึงสิ่งนี้อีกเล็กน้อยในความคิดเห็นด้านบน


9

อัปเดตสำหรับปี 2014

เมื่อใช้ jQuery เวอร์ชันล่าสุดตอนนี้คุณสามารถยกเลิกการผูกเหตุการณ์ทั้งหมดในเนมสเปซได้ง่ายๆ $( "#foo" ).off( ".myNamespace" );



8

สำหรับremove ทุก event-handlersคนนี่คือสิ่งที่ได้ผลสำหรับฉัน:

ลบกิจกรรมทั้งหมดขนย้ายหมายถึงการที่จะมีที่ราบHTML structureโดยไม่ต้องทั้งหมดevent handlersที่แนบมากับและelement child nodesเมื่อต้องการทำเช่นนี้jQuery's clone()ช่วย

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

ด้วยสิ่งนี้เราจะมีการcloneแทนที่originalด้วยไม่มีevent-handlersใน

โชคดี...


7

ขอบคุณสำหรับข้อมูล. มีประโยชน์มากฉันใช้เพื่อล็อคการโต้ตอบหน้าเว็บในขณะที่อยู่ในโหมดแก้ไขโดยผู้ใช้รายอื่น ฉันใช้มันร่วมกับ ajaxComplete ไม่จำเป็นต้องมีพฤติกรรมเดียวกัน แต่ค่อนข้างคล้ายกัน

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

function executePageLock(){
    //do something
}

5

ในกรณีที่มี.on()การใช้วิธีการก่อนหน้านี้กับตัวเลือกเฉพาะเช่นในตัวอย่างต่อไปนี้:

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

ทั้งสองunbind()และ.off()วิธีการจะไม่ทำงาน

อย่างไรก็ตามสามารถใช้วิธี . undelegate ()เพื่อลบตัวจัดการออกจากเหตุการณ์สำหรับองค์ประกอบทั้งหมดที่ตรงกับตัวเลือกปัจจุบัน:

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

1
ฉันเลื่อนทั้งหน้าขณะที่มองหาวิธีแก้ปัญหานี้ทำงานเหมือนมีเสน่ห์
Abhishek Pandey

4

หากคุณใช้$(document).on()เพื่อเพิ่มผู้ฟังไปยังองค์ประกอบที่สร้างขึ้นแบบไดนามิกคุณอาจต้องใช้สิ่งต่อไปนี้เพื่อลบออก:

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

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


2

หากคุณตั้งค่าonclickผ่านที่htmlคุณต้องการremoveAttr ($(this).removeAttr('onclick'))

หากคุณตั้งค่าผ่าน jquery (หลังจากคลิกครั้งแรกในตัวอย่างของฉันด้านบน) จากนั้นคุณต้อง unbind($(this).unbind('click'))


2

ฉันรู้ว่าสิ่งนี้มาถึงช้า แต่ทำไมไม่ใช้ JS ธรรมดาเพื่อลบกิจกรรม

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

หรือถ้าคุณใช้ฟังก์ชั่นที่มีชื่อเป็นตัวจัดการเหตุการณ์:

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

คำแนะนำที่ดีฉันชอบที่จะใช้จาวาสคริปต์ดั้งเดิมเมื่อมีให้บริการ
Michiel

1

วิธีการทั้งหมดที่อธิบายไม่สามารถใช้งานได้สำหรับฉันเพราะฉันเพิ่มเหตุการณ์การคลิกon()ไปยังเอกสารที่มีการสร้างองค์ประกอบในเวลาทำงาน:

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


วิธีแก้ปัญหาของฉัน:

เนื่องจากฉันไม่สามารถแยกคลาส ".button" ฉันเพิ่งกำหนดคลาสอื่นให้กับปุ่มที่มีสไตล์ CSS เดียวกัน ด้วยการทำเช่นนั้น live / on-event-handler จะไม่สนใจการคลิกในที่สุด

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

หวังว่าจะช่วย


1

หวังว่ารหัสด้านล่างของฉันจะอธิบายทั้งหมด 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
ทำไมคุณถึง })(jQuery);เข้าสู่ IIFE เมื่อสามารถเข้าถึงได้ทั่วโลกแล้ว?
ไบรอัน P

2
เป็นคำถามที่ดีไบรอัน วิธีการนี้ถูกป้อนในยีนของฉันเนื่องจากการปฏิบัติ - มีความเป็นไปได้ที่ปลั๊กอินที่ไม่ใช่ jquery อาจมีตัวแปร $ ดังนั้นฉันไม่สามารถใช้ $ โดยตรงได้ - การใช้คำว่า "jQuery" บ่อยครั้งในไฟล์สคริปต์ js สามารถเพิ่มขนาดไบต์ของไฟล์โดยที่ jQuery เป็นสตริง 6 ไบต์ ดังนั้นฉันต้องการใช้ "$" หรือตัวแปรใด ๆ ของไบต์เดียว
mysticmo

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.