ฉันผูกเหตุการณ์การคลิกด้วยปุ่ม:
$('#myButton').bind('click', onButtonClicked);
ในสถานการณ์หนึ่งสิ่งนี้ถูกเรียกหลายครั้งดังนั้นเมื่อฉันทำtrigger
ฉันเห็นการโทรของ ajax หลายครั้งซึ่งฉันต้องการป้องกัน
ฉันจะทำอย่างไรbind
ถ้ามันไม่เคยผูกพันมาก่อน
ฉันผูกเหตุการณ์การคลิกด้วยปุ่ม:
$('#myButton').bind('click', onButtonClicked);
ในสถานการณ์หนึ่งสิ่งนี้ถูกเรียกหลายครั้งดังนั้นเมื่อฉันทำtrigger
ฉันเห็นการโทรของ ajax หลายครั้งซึ่งฉันต้องการป้องกัน
ฉันจะทำอย่างไรbind
ถ้ามันไม่เคยผูกพันมาก่อน
คำตอบ:
อัปเดต 24 ส.ค. 55 : ใน jQuery 1.8 จะไม่สามารถเข้าถึงเหตุการณ์ขององค์ประกอบโดยใช้.data('events')
ไฟล์. (ดูรายละเอียดจุดบกพร่องนี้ ) เป็นไปได้ที่จะเข้าถึงข้อมูลเดียวกันด้วยjQuery._data(elem, 'events')
โครงสร้างข้อมูลภายในซึ่งไม่เป็นเอกสารดังนั้นจึงไม่รับประกัน 100% ว่าจะยังคงเสถียร อย่างไรก็ตามสิ่งนี้ไม่ควรเป็นปัญหาและสามารถเปลี่ยนบรรทัดที่เกี่ยวข้องของโค้ดปลั๊กอินด้านบนเป็นดังต่อไปนี้:
var data = jQuery._data(this[0], 'events')[type];
เหตุการณ์ jQuery ถูกเก็บไว้ในวัตถุข้อมูลที่เรียกว่าevents
ดังนั้นคุณสามารถค้นหาในสิ่งนี้:
var button = $('#myButton');
if (-1 !== $.inArray(onButtonClicked, button.data('events').click)) {
button.click(onButtonClicked);
}
แน่นอนว่าจะเป็นการดีที่สุดหากคุณสามารถจัดโครงสร้างแอปพลิเคชันของคุณเพื่อให้มีการเรียกรหัสนี้เพียงครั้งเดียว
สิ่งนี้สามารถห่อหุ้มไว้ในปลั๊กอิน:
$.fn.isBound = function(type, fn) {
var data = this.data('events')[type];
if (data === undefined || data.length === 0) {
return false;
}
return (-1 !== $.inArray(fn, data));
};
จากนั้นคุณสามารถโทร:
var button = $('#myButton');
if (!button.isBound('click', onButtonClicked)) {
button.click(onButtonClicked);
}
<a>
อะไร เพราะเมื่อฉันลองมันบอกjQuery._data()
ข้อผิดพลาดต่อไปนี้TypeError: a is undefined
var data = jQuery._data(this[0], 'events')[type];
ในการลองจับและส่งคืนเท็จในการจับ หากไม่มีเหตุการณ์ใดผูกมัดกับ [0] นี้นอกจากการเรียกไปที่ [type] จะทำให้เกิดการเปลี่ยนแปลงบางอย่างของ "ไม่สามารถรับคุณสมบัติ 'คลิก' ของการอ้างอิงที่ไม่ได้กำหนดหรือเป็นค่าว่าง" และเห็นได้ชัดว่านั่นจะบอกสิ่งที่คุณต้องรู้ด้วย
for (var i = 0; i < data.length; i++) { if (data[i].handler.toString() === fn.toString()) { return true; } }
อีกวิธีหนึ่ง - ทำเครื่องหมายปุ่มดังกล่าวด้วยคลาส CSS และตัวกรอง:
$('#myButton:not(.bound)').addClass('bound').bind('click', onButtonClicked);
ใน jQuery เวอร์ชันล่าสุดแทนที่bind
ด้วยon
:
$('#myButton:not(.bound)').addClass('bound').on('click', onButtonClicked);
หากใช้ jQuery 1.7+:
โทรoff
มาก่อนได้ที่on
:
$('#myButton').off('click', onButtonClicked) // remove handler
.on('click', onButtonClicked); // add handler
ถ้าไม่:
คุณสามารถเลิกผูกเหตุการณ์แรกได้:
$('#myButton').unbind('click', onButtonClicked) //remove handler
.bind('click', onButtonClicked); //add handler
.unbind('click', onButtonClicked)
หนึ่งจัดการ: ดูคู่มือ
$(sel).unbind("click.myNamespace");
$('#myButton').unbind('click', onButtonClicked).bind('click', onButtonClicked);
วิธีที่ดีที่สุดที่ฉันเห็นคือใช้ live () หรือ delegate () เพื่อจับภาพเหตุการณ์ในพาเรนต์ไม่ใช่ในแต่ละองค์ประกอบย่อย
หากปุ่มของคุณอยู่ในองค์ประกอบ #parent คุณสามารถแทนที่:
$('#myButton').bind('click', onButtonClicked);
โดย
$('#parent').delegate('#myButton', 'click', onButtonClicked);
แม้ว่า #myButton จะยังไม่มีเมื่อเรียกใช้รหัสนี้
ฉันเขียนปลั๊กอินเล็ก ๆ ที่เรียกว่า "ครั้งเดียว" ซึ่งทำเช่นนั้น ดำเนินการปิดและเปิดในองค์ประกอบ
$.fn.once = function(a, b) {
return this.each(function() {
$(this).off(a).on(a,b);
});
};
และง่ายๆ:
$(element).once('click', function(){
});
off
ลบตัวจัดการทั้งหมดสำหรับประเภทที่ระบุ? หมายความว่าถ้ามีตัวจัดการการคลิกแยกต่างหากที่ไม่เกี่ยวข้อง แต่อยู่ในรายการเดียวกันจะไม่ถูกลบออกไปด้วยหรือ
ทำไมไม่ใช้สิ่งนี้
unbind()
ก่อน bind()
$('#myButton').unbind().bind('click', onButtonClicked);
$('#myButton').off().on('click', onButtonClicked);
ยังใช้ได้กับฉัน
นี่คือเวอร์ชันของฉัน:
Utils.eventBoundToFunction = function (element, eventType, fCallback) {
if (!element || !element.data('events') || !element.data('events')[eventType] || !fCallback) {
return false;
}
for (runner in element.data('events')[eventType]) {
if (element.data('events')[eventType][runner].handler == fCallback) {
return true;
}
}
return false;
};
การใช้งาน:
Utils.eventBoundToFunction(okButton, 'click', handleOkButtonFunction)
อ้างอิงจากคำตอบของ @ konrad-garus แต่การใช้data
เนื่องจากฉันเชื่อว่าclass
ควรใช้เป็นส่วนใหญ่ในการจัดแต่งทรงผม
if (!el.data("bound")) {
el.data("bound", true);
el.on("event", function(e) { ... });
}
เพื่อหลีกเลี่ยงการตรวจสอบ / ผูก / เลิกผูกคุณสามารถเปลี่ยนแนวทางของคุณได้! ทำไมคุณไม่ใช้ Jquery .on ()?
เนื่องจาก Jquery 1.7, .live (), .delegate () เลิกใช้งานแล้วตอนนี้คุณสามารถใช้. on () ถึง
แนบตัวจัดการเหตุการณ์สำหรับองค์ประกอบทั้งหมดที่ตรงกับตัวเลือกปัจจุบันในตอนนี้และในอนาคต
หมายความว่าคุณสามารถแนบเหตุการณ์กับองค์ประกอบหลักที่ยังคงมีอยู่และแนบองค์ประกอบลูกไม่ว่าจะมีอยู่หรือไม่ก็ตาม!
เมื่อคุณใช้. on () เช่นนี้:
$('#Parent').on('click', '#myButton' onButtonClicked);
คุณจับเหตุการณ์คลิกที่ผู้ปกครองและค้นหาลูก '#myButton' ถ้ามี ...
ดังนั้นเมื่อคุณลบหรือเพิ่มองค์ประกอบลูกคุณไม่ต้องกังวลว่าจะเพิ่มหรือลบการเชื่อมโยงเหตุการณ์หรือไม่
.off
ซึ่งฉันเชื่อว่าจะลบตัวจัดการที่ไม่เกี่ยวข้องออกไปในกระบวนการ
ลอง:
if (typeof($("#myButton").click) != "function")
{
$("#myButton").click(onButtonClicked);
}
if ($("#btn").data('events') != undefined && $("#btn").data('events').click != undefined) {
//do nothing as the click event is already there
} else {
$("#btn").click(function (e) {
alert('test');
});
}
เมื่อเดือนมิถุนายน 2019 ฉันได้อัปเดตฟังก์ชันแล้ว (และใช้ได้กับสิ่งที่ฉันต้องการ)
$.fn.isBound = function (type) {
var data = $._data($(this)[0], 'events');
if (data[type] === undefined || data.length === 0) {
return false;
}
return true;
};
JQuery มีวิธีแก้ไข :
$( "#foo" ).one( "click", function() {
alert( "This will be displayed only once." );
});
เทียบเท่า:
$( "#foo" ).on( "click", function( event ) {
alert( "This will be displayed only once." );
$( this ).off( event );
});