ฉันจะส่งอาร์กิวเมนต์ไปยังตัวจัดการเหตุการณ์ใน jQuery ได้อย่างไร


92

ด้วยรหัส jQuery เช่น:

$("#myid").click(myfunction);

function myfunction(arg1, arg2) {/* something */}

ฉันจะส่งอาร์กิวเมนต์ไปmyfunctionยังในขณะที่ใช้ jQuery ได้อย่างไร


คำตอบ:


111

วิธีที่ง่ายที่สุดคือทำเช่นนั้น (สมมติว่าคุณไม่ต้องการให้ข้อมูลเหตุการณ์ใด ๆ ส่งผ่านไปยังฟังก์ชัน) ...

$("#myid").click(function() {
    myfunction(arg1, arg2);
});

jsFiddle

สิ่งนี้จะสร้างฟังก์ชันที่ไม่ระบุตัวตนซึ่งถูกเรียกใช้เมื่อclickเหตุการณ์ถูกทริกเกอร์ สิ่งนี้จะเรียกmyfunction()ด้วยอาร์กิวเมนต์ที่คุณระบุ

หากคุณต้องการที่จะให้ThisBinding(ค่าของthisเมื่อฟังก์ชั่นที่มีการเรียกการตั้งค่าเป็นองค์ประกอบที่เรียกเหตุการณ์นี้) call()จากนั้นเรียกใช้ฟังก์ชันที่มี

$("#myid").click(function() {
    myfunction.call(this, arg1, arg2);
});

jsFiddle

คุณไม่สามารถผ่านการอ้างอิงโดยตรงในทางที่รัฐตัวอย่างของคุณหรืออาร์กิวเมนต์เดียวมันจะเป็นjQueryeventวัตถุ

หากคุณไม่ต้องการที่จะผ่านการอ้างอิงที่คุณจะต้องใช้ประโยชน์จากของ jQuery proxy()ฟังก์ชั่น (ซึ่งเป็นเสื้อคลุมเบราว์เซอร์ข้ามFunction.prototype.bind()) นี้จะช่วยให้คุณผ่านการขัดแย้งซึ่งถูกผูกไว้ก่อนeventโต้แย้ง

$("#myid").click($.proxy(myfunction, null, arg1, arg2));   

jsFiddle

ในตัวอย่างนี้myfunction()จะได้รับการดำเนินการที่มีThisBindingเหมือนเดิม ( nullไม่ได้เป็นวัตถุดังนั้นปกติthisมูลค่าขององค์ประกอบที่เรียกเหตุการณ์นี้ถูกนำมาใช้) พร้อมกับการขัดแย้ง (ตามลำดับ) arg1, arg2และในที่สุดก็ jQuery eventวัตถุที่คุณสามารถละเลย ถ้าไม่จำเป็น (อย่าแม้แต่ตั้งชื่อในอาร์กิวเมนต์ของฟังก์ชัน)

คุณยังสามารถใช้ use the jQuery eventobject dataเพื่อส่งผ่านข้อมูลได้ แต่จะต้องมีการแก้ไขmyfunction()เพื่อเข้าถึงผ่านevent.data.arg1(ซึ่งไม่ใช่อาร์กิวเมนต์ของฟังก์ชันเช่นเดียวกับคำถามของคุณที่กล่าวถึง) หรืออย่างน้อยก็แนะนำฟังก์ชันพร็อกซีแบบแมนนวลเหมือนตัวอย่างในอดีตหรือที่สร้างขึ้น โดยใช้ตัวอย่างหลัง


2
โปรดทราบว่าคุณจะสูญเสียบริบท jquery $ (this) ใน myfunction () เพื่อรักษาให้โทรmyfunction(this, arg1, arg2)จากตัวจัดการที่ไม่ระบุชื่อ จากนั้นฟังก์ชั่นของคุณก็ทำได้myfunction(el, arg1, arg2) { alert($(el).val()); }
lambinator

11
@geosteve: myfunction.call(this, arg1, arg2)ถ้าคุณต้องการที่จะเก็บไว้ใช้
alex

1
นั่นไม่ใช่การส่งผ่านอาร์กิวเมนต์ไปยังฟังก์ชันตามที่คำถามถาม เรียกใช้ฟังก์ชันที่เรียกใช้ฟังก์ชันอื่น ฟังก์ชันการซ้อนภายในฟังก์ชันที่ไม่ระบุตัวตนไม่ใช่ความคิดที่ดีเนื่องจากคุณไม่สามารถยกเลิกการเชื่อมฟังก์ชันนิรนามได้อย่างง่ายดาย
George Filippakos

1
@ geo1701 คุณสามารถทำได้ถ้าคุณใช้เนมสเปซที่กำหนดเองและผูกกับมันเพียงครั้งเดียว สำหรับวัตถุประสงค์ส่วนใหญ่ก็ใช้ได้ แต่คุณจะเสียประโยชน์ที่คุณกล่าวถึง
alex

1
เห็นด้วยกับ @ geo1701 ฉันต้องลบตัวจัดการเหตุการณ์และวิธีแก้ปัญหาของเขาเป็นเพียงวิธีเดียวที่ใช้งานได้
Pavel K

77
$("#myid").on('click', {arg1: 'hello', arg2: 'bye'}, myfunction);

function myfunction(e) {

    var arg1 = e.data.arg1;
    var arg2 = e.data.arg2;

    alert(arg1);
    alert(arg2);

}

//call method directly:
myfunction({
    arg1: 'hello agian', 
    arg2: 'bye again'
});

ยังช่วยให้คุณสามารถผูกและคลายตัวจัดการเหตุการณ์เฉพาะโดยใช้วิธีการเปิดและปิด

ตัวอย่าง:

$("#myid").off('click', myfunction);

สิ่งนี้จะยกเลิกการเชื่อมตัวจัดการ myfunction จาก #myid


นั่นไม่ใช่การส่งผ่านอาร์กิวเมนต์ไปยังฟังก์ชันตามที่คำถามถาม
alex

4
นั่นคือวิธีที่คุณส่งผ่านข้อโต้แย้ง (คุณรวมไว้ในวัตถุ)
George Filippakos

เป็นวิธีที่คุณส่งผ่านข้อมูล แต่เป็นการเรียกใช้อาร์กิวเมนต์ฟังก์ชัน
alex

7
เป็นวิธีแก้ปัญหาที่ดีกว่าสำหรับคำตอบที่ได้รับการยอมรับเนื่องจากใช้รูปแบบการเชื่อมโยงและการคลายการผูกมัดที่แนะนำโดยใช้วิธีเปิด / ปิด
George Filippakos

7
หากคุณคิดว่าการไม่ผูกมัดนั้นค่อนข้างหายากคุณต้องมีประสบการณ์ที่ จำกัด มาก โปรดอย่าสนับสนุน poo poo จากผู้อื่น - นี่คือฐานความรู้โดยรวมไม่ใช่การแข่งขัน ไม่มีคำตอบที่ถูกหรือผิด
George Filippakos

12

ในขณะที่คุณควรใช้คำตอบของ Alex อย่างแน่นอนวิธีการ "ผูก" ของไลบรารีต้นแบบได้รับการกำหนดมาตรฐานแล้วใน Ecmascript 5 และจะนำไปใช้ในเบราว์เซอร์ในไม่ช้า มันทำงานดังนี้:

jQuery("#myid").click(myfunction.bind(this, arg1, arg2));

2
จะthisถูกตั้งค่าเป็นบริบทที่แตกต่างกันหากคุณใช้วิธีนี้ตัวอย่างเช่นการนำbind()เข้าthisในบริบทนั้น (ส่วนกลาง) อาจส่งผลให้ตัวจัดการการคลิกนั้นมีwindowวัตถุthisตรงข้ามกับการอ้างอิงถึง#myidองค์ประกอบหรือไม่
alex

2
@alex คุณค่อนข้างถูกต้อง jQuery จะผูกองค์ประกอบ #myid กับ 'this' ในตัวจัดการเหตุการณ์และการใช้วิธีการผูกจะแทนที่สิ่งนั้น ฉันเขียนโพสต์นี้เมื่อหลายปีก่อนดูเหมือนว่ามันจะยากที่จะพูดว่าฉันคิดอะไรอยู่ในตอนนั้น ฉันเดาว่าฉันแค่คิดว่าคนที่อ่านคำตอบของฉันฉลาดพอที่จะเข้าใจรายละเอียดเหล่านี้ด้วยตัวเอง
Breton

12
นั่นเป็นข้อสันนิษฐานที่อันตรายมาก
Travis

@Travis จากการเขียนนี้ (เกือบ 11 ปีหลังจากคำตอบของ Breton) caniuse.com รายงานว่า Ecmascript 5 ได้รับการสนับสนุนโดย98.87%ของเบราว์เซอร์ (ดูcaniuse.com/#search=ECMAScript%205 )
Stephan

1
@Stephan ความคิดเห็นpeople reading my answers are smart enough to figure these details out themselvesเกี่ยวกับลิ้นของฉันมุ่งเป้าไปที่ @Breton เพื่อสมมติไม่ใช่เกี่ยวกับ Ecmascript
Travis

6

กระทู้เก่า แต่เพื่อการค้นหา; ลอง:

$(selector).on('mouseover',...);

... และตรวจสอบพารามิเตอร์ "data": http://api.jquery.com/on/

เช่น:

function greet( event ) {
  alert( "Hello " + event.data.name );
}
$( "button" ).on( "click", {name: "Karl"}, greet );
$( "button" ).on( "click", {name: "Addy"}, greet );

4

มีคำตอบที่ดีอยู่แล้ว แต่อย่างไรก็ตามนี่คือสองเซ็นต์ของฉัน คุณยังสามารถใช้:

$("#myid").click({arg1: "foo", arg2: "bar"}, myfunction)

และผู้ฟังจะมีลักษณะดังนี้:

function myfunction(event){ alert(event.data.arg1); alert(event.data.arg2); }


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