ฉันมีรหัสต่อไปนี้:
function someMethod()
{
$(obj).click(function {});
}
someMethod ถูกเรียกสองครั้งและทำให้เหตุการณ์คลิกถูกผูกสองครั้ง ฉันจะผูกมันเพียงครั้งเดียวได้อย่างไร?
ฉันมีรหัสต่อไปนี้:
function someMethod()
{
$(obj).click(function {});
}
someMethod ถูกเรียกสองครั้งและทำให้เหตุการณ์คลิกถูกผูกสองครั้ง ฉันจะผูกมันเพียงครั้งเดียวได้อย่างไร?
คำตอบ:
หากคุณสามารถนำไปใช้ได้อาจต้องการดูที่event.preventDefaultและevent.stopPropagation หรือเลิกผูกและผูกแต่ละครั้งภายในวิธีการของคุณเช่น
function someMethod()
{
$(obj).off('click').on('click', function(e) {
// put your logic in here
});
}
function someMethod() { $(obj).off('click.namespace').on('click.namespace', function {}); }
นอกเหนือจากคำตอบของ pna แล้วคุณอาจต้องการคิดถึงการตั้งชื่อเหตุการณ์ของคุณเพื่อที่คุณจะได้ไม่ไปเชื่อมโยงเหตุการณ์การคลิกทั้งหมดโดยไม่ได้ตั้งใจ
function someMethod () { $ (obj) .unbind ('click.namespace') ผูก ('click.namespace', function () {}); }
$(obj).off()
และ$(obj).on()
ตามลำดับ มิฉะนั้นเนมสเปซจะช่วยได้และสิ่งนี้ได้ผล ขอบคุณ!
ไม่มีเมธอดในตัวเพื่อตรวจสอบว่าคุณได้ผูกฟังก์ชันนี้ไว้แล้วหรือไม่ คุณสามารถเชื่อมโยงฟังก์ชันการคลิกหลายรายการเข้ากับวัตถุได้ ตัวอย่างเช่น:
$('#id').bind('click', function(){
alert('hello');
});
$('#id').bind('click', function(){
alert('goodbuy');
});
หากคุณทำตามข้างต้นเมื่อวัตถุถูกคลิกมันจะแจ้งเตือนสวัสดีแล้วลาก่อน เพื่อให้แน่ใจว่ามีเพียงฟังก์ชันเดียวเท่านั้นที่เชื่อมโยงกับเหตุการณ์การคลิกให้เลิกผูกตัวจัดการเหตุการณ์การคลิกจากนั้นผูกฟังก์ชันที่ต้องการดังนี้:
$(obj).unbind('click').bind('click', function(){... });
วิธีแก้ปัญหาที่ชัดเจนคืออย่าโทรsomeMethod()
ซ้ำสองครั้ง หากคุณไม่สามารถแก้ไขได้คุณสามารถเก็บตัวแปรสถานะไว้เพื่อที่จะผูกเพียงครั้งเดียวดังนี้:
function someMethod()
{
if (!someMethod.bound) {
$(obj).click(function() {});
someMethod.bound = true;
}
}
หมายเหตุ: สิ่งนี้ใช้คุณสมบัติของฟังก์ชันเองแทนที่จะแนะนำตัวแปรส่วนกลางเพื่อติดตามว่าถูกผูกไว้หรือไม่ คุณยังสามารถใช้คุณสมบัติกับวัตถุนั้นเอง
คุณสามารถดูได้ทำงานที่นี่: http://jsfiddle.net/jfriend00/VHkxu/
หรือใช้ฟังก์ชัน one () ของ jQuery ซึ่งคล้ายกับ on () แต่จะยิงเหตุการณ์เพียงครั้งเดียวแม้ว่าคุณจะผูกไว้หลายครั้งก็ตาม
jQuery ทำให้การเรียกใช้ฟังก์ชันบางอย่างทำได้ง่ายเพียงครั้งเดียว:
function someMethod()
{
$(obj).click(function() {});
this.someMethod = $.noop;
}
jQuery.noop
สั้นกว่าอักขระเพียงตัวเดียวfunction(){}
ดังนั้นจึงเป็นเรื่องโง่ที่บอกว่า "ช่วย" ตรงนี้เพียงแค่ให้ฟังก์ชันว่างเปล่า นี่คือตัวอย่างที่ไม่ใช่วิธีการของ jQuery ของโซลูชันทั่วไปนี้:var fn = function(){ fn = function(){}; do stuff; };
$
แทน
นี่เป็นข้อเสนอแนะเนื่องจากฉันไม่ทราบตรรกะของคุณ อาจหรือไม่ได้ผลสำหรับคุณ
ลองรวม jquery live () และหนึ่ง () ฟังก์ชั่นจะให้ผลลัพธ์ที่ดีกว่าการย้อนเหตุการณ์
กรณีพิเศษจะใช้ได้เมื่อคุณมีองค์ประกอบ DOM 2 รายการ (แม่และลูก) Live () ที่โหนดแม่ทำให้แน่ใจว่าเหตุการณ์จะถูกเรียกใช้จากนั้นเรียกหนึ่ง () เพื่อลงทะเบียนเหตุการณ์แบบไดนามิกซึ่งจะดำเนินการเพียงครั้งเดียว (ซึ่งมีฟังก์ชันการทำงานที่คล้ายกันเช่น rebinds)
One()
ฟังก์ชั่นการทำงานในchrome
แต่ไม่ได้ทำงานในในsafari
Mac
คุณสามารถเพิ่มคลาส css ให้กับองค์ประกอบที่ถูกผูกแล้วกรองออก:
function someMethod()
{
$(obj).not('.click-binded')
.click(function {})
.addClass('click-binded');
}
วิธีนี้อาจใช้กับปลั๊กอิน:
$(obj).not('.datetimepicker-applied')
.datetimepicker()
.addClass('datetimepicker-applied');
var bound = false;
function someMethod()
{
if(!bound)
{
$(obj).click(function {});
bound = true;
}
}
แต่ฉันอาจจะตรวจสอบว่าทำไมจึงถูกเรียกสองครั้งก่อนที่จะทำการแก้ปัญหาบางอย่าง
bound
ติดอยู่someMethod()
แทนที่จะสร้างมลพิษให้กับพื้นที่ชื่อทั่วโลก
หากคุณต้องการผูกกับวัตถุเพียงครั้งเดียวคุณควรใช้แฟล็กและยึดติดกับวัตถุนั้น
ตัวอย่างเช่น:
if($('#id') && $('#id').data('done') == null)) {
$('#id').bind('click', function() {
alert('hello');
});
$('#id').data('done', true);
}
คุณสามารถใช้ฟังก์ชันส่วนขยาย jQuery นี้
$.fn.once = function (type, fn, uid) {
if(uid == undefined) {
console.error("Called $.once without uid\n", this, "\n", fn);
}
var dataStr = type+"-handler-"+uid;
if(!this.data(dataStr)) {
this.data(dataStr, true);
this.on(type, fn);
}
};
แทนที่จะทำเช่นนี้
$("button").on("click", function(){
alert("You Clicked On A Button");
});
ยาทำอย่างนี้
$("button").once("click", function(){
alert("You Clicked On A Button");
}, "btnHandler");
ตอนนี้เมื่อฉันมีฟังก์ชั่นรอบ ๆ
function addBtnHandler() {
$("button").once("click", function() {
alert("You Clicked On A Button");
}, "btnHandler");
}
และฉันเรียกมันหลายครั้ง
addBtnHandler();
addBtnHandler();
addBtnHandler();
ทำเพียงครั้งเดียว
สังเกตว่าส่วนขยายทำงานโดยการตรวจสอบทั้ง uid และ type ซึ่งหมายความว่าคุณสามารถผูกตัวจัดการประเภทต่างๆด้วย uid เดียวกันคุณอาจต้องการหรือไม่ต้องการก็ได้ หากต้องการเปลี่ยนแปลงแก้ไข
var dataStr = type+"-handler-"+uid;
ด้วยสิ่งที่ชอบ
var dataStr = "handler-"+uid;
ฉันยังพยายามใช้วิธีปิดและบน jquery สำหรับการผูกเหตุการณ์เพียงครั้งเดียวกับองค์ประกอบ dom ที่ยังไม่มีอยู่หรือยังไม่ได้สร้างองค์ประกอบ dom
$('.select').off('event').on('event', 'selector', function(e){ // });
รหัสนี้ทำงานไม่ถูกต้อง
ฉันเจอวิธีที่มีกำไรมากนั่นคือวิธี 'หนึ่ง' มีประโยชน์มากเมื่อคุณต้องการผูกเหตุการณ์เพียงครั้งเดียว
คุณสามารถค้นหาเอกสารได้ที่นี่ http://api.jquery.com/one/
สิ่งนี้เหมือนกับ method "on" แต่แตกต่างกันที่ลักษณะการทำงานของมันคือไม่ยึดติดกับเหตุการณ์สำหรับตัวเลือกหลายตัว
$('body').one('click', 'selector', function(){ // do your stuff here });
คุณสามารถทำได้ด้วย JS บริสุทธิ์โดยใช้เมธอดaddEventListenerและตัวเลือกครั้งเดียวของเขา
target.addEventListener('click', handler, {once: true});