การจัดการเหตุการณ์ช่องทำเครื่องหมาย jQuery


136

ฉันมีดังต่อไปนี้:

<form id="myform">
   <input type="checkbox" name="check1" value="check1">
   <input type="checkbox" name="check2" value="check2">
</form>

ฉันจะใช้ jQuery เพื่อจับภาพเหตุการณ์การตรวจสอบใด ๆ ที่เกิดขึ้นmyformและบอกว่าช่องทำเครื่องหมายใดถูกสลับ (และรู้ว่ามันถูกสลับหรือปิด)

คำตอบ:


244
$('#myform :checkbox').change(function() {
    // this will contain a reference to the checkbox   
    if (this.checked) {
        // the checkbox is now checked 
    } else {
        // the checkbox is now no longer checked
    }
});

30
thisถูกตั้งค่าเป็นองค์ประกอบ DOM ของช่องทำเครื่องหมายแล้วจึงthis.checkedเพียงพอ คุณไม่จำเป็นต้องสร้างวัตถุ jQuery อีกชิ้นเว้นแต่คุณจะวางแผนจัดการมัน
Walf

18
เพียงปลายเล็กน้อย คุณจะได้รับประสิทธิภาพที่เพิ่มขึ้นโดยใช้ช่องทำเครื่องหมาย: ช่องทำเครื่องหมายในตัวเลือกของคุณแทนเพียง: ช่องทำเครื่องหมายเนื่องจากตัวหลังถูกแปลเป็นตัวเลือกสากล *: ช่องทำเครื่องหมาย
jimmystormig

23
คลิกไม่ได้อยู่ใกล้กับกิจกรรมตรวจสอบใด ๆ
ปีเตอร์

27
นี่ไม่ใช่คำตอบที่ดีที่สุด หากคุณมีป้ายกำกับที่สอดคล้องกันสำหรับการป้อนข้อมูลของคุณ (เช่น<label for='myInput'>Checkbox:</label><input id='myInput' name='myInput' type='checkbox'/>) และคุณคลิกที่ป้ายกำกับช่องทำเครื่องหมายจะถูกตรวจสอบ แต่ฟังก์ชั่นนี้จะไม่ถูกเรียก คุณควรใช้.change()เหตุการณ์
Patrick

7
คำตอบนี้ไม่ได้ให้คำตอบอย่างเต็มที่ - โปรดดูคำตอบของ Anurag ด้านล่างซึ่งเป็นคำตอบที่สมบูรณ์มากขึ้น (และถูกต้อง) คำตอบนี้ถูกต้องบางส่วนแน่นอน แต่ตามที่ระบุไว้มันไม่ใช่คำตอบที่ดีที่สุด
Carnix

131

ใช้เหตุการณ์การเปลี่ยนแปลง

$('#myform :checkbox').change(function() {
    // this represents the checkbox that was checked
    // do something with it
});

5
หากช่องทำเครื่องหมายถูกซ่อนอยู่ผู้ใช้จะไม่สามารถโต้ตอบกับมันได้ แจ้งให้เราทราบหากคุณหมายถึงอย่างอื่น
Anurag

1
$("input[name=check1]").prop('checked', true)นี้ไม่ได้ไฟ ดูjsfiddle.net/Z3E8V/2
Peter

15
นั่นคือจากการออกแบบ การเปลี่ยนคุณสมบัติขององค์ประกอบ DOM โดยทางโปรแกรมไม่ทริกเกอร์ตัวจัดการเหตุการณ์ที่เกี่ยวข้อง คุณจะต้องยิงด้วยตนเอง
Anurag

6
นี่ควรเป็นคำตอบที่เลือกซึ่งครอบคลุมการคลิกที่ป้ายกำกับของช่องทำเครื่องหมาย
Patrick

3
จากเอกสาร jQuery: "เนื่องจาก:checkboxเป็นส่วนขยาย jQuery และไม่ใช่ส่วนหนึ่งของข้อมูลจำเพาะ CSS การสืบค้นที่ใช้:checkboxจึงไม่สามารถใช้ประโยชน์จากการเพิ่มประสิทธิภาพที่จัดทำโดยquerySelectorAll()วิธีDOM ดั้งเดิมเพื่อประสิทธิภาพที่ดีขึ้นในเบราว์เซอร์สมัยใหม่ให้ใช้[type="checkbox"]แทน"
NXT

54

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

  • ฟังสำหรับclickเหตุการณ์checkboxesคือไม่ได้เป็นความคิดที่ดีที่สุดเท่าที่จะไม่อนุญาตให้มีการสลับแป้นพิมพ์หรือการเปลี่ยนแปลงที่ทำที่ตรงกับlabelองค์ประกอบที่ถูกคลิก รับฟังchangeเหตุการณ์เสมอ

  • ใช้ jQuery หลอกตัวเลือกมากกว่า:checkbox สั้นและอ่านง่ายขึ้นinput[type=checkbox]:checkbox

  • ใช้is()กับ jQuery :checkedpseudo-selector เพื่อทดสอบว่ามีการทำเครื่องหมายที่เช็คบ็อกซ์หรือไม่ สิ่งนี้รับประกันว่าจะทำงานได้กับทุกเบราว์เซอร์

ตัวจัดการเหตุการณ์พื้นฐานที่แนบกับองค์ประกอบที่มีอยู่:

$('#myform :checkbox').change(function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/2/

หมายเหตุ:

  • ใช้:checkboxตัวเลือกที่ต้องการใช้input[type=checkbox]
  • เชื่อมต่อนี้เพียงองค์ประกอบที่ตรงกับที่มีอยู่ในเวลาที่เหตุการณ์นี้จะได้รับการจดทะเบียน

ตัวจัดการเหตุการณ์ที่ได้รับมอบหมายติดกับองค์ประกอบบรรพบุรุษ:

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

$('#myform').on('change', ':checkbox', function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/4/

หมายเหตุ:

  • วิธีนี้ใช้งานได้โดยฟังเหตุการณ์ (ในกรณีนี้change) เพื่อทำให้ฟองดูองค์ประกอบของบรรพบุรุษที่ไม่เปลี่ยนแปลง (ในกรณีนี้#myform)
  • มันแล้วใช้ตัวเลือก jQuery ( ':checkbox'ในกรณีนี้) กับองค์ประกอบเฉพาะในห่วงโซ่ฟอง
  • มันแล้วใช้ฟังก์ชั่นการจัดการเหตุการณ์เฉพาะผู้ที่ตรงกันองค์ประกอบที่ทำให้เกิดเหตุการณ์
  • ใช้documentเป็นค่าเริ่มต้นเพื่อเชื่อมต่อตัวจัดการเหตุการณ์ที่ได้รับมอบหมายหากไม่มีสิ่งใดใกล้กว่า / สะดวกกว่า
  • อย่าใช้bodyเพื่อแนบเหตุการณ์ที่ได้รับมอบหมายเนื่องจากมีข้อผิดพลาด (เกี่ยวข้องกับการใส่สไตล์) ที่สามารถหยุดการรับเหตุการณ์เมาส์ได้

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

ถาม: ช้าลงไหม

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


ทำไมไม่ prop('checked', true)เริ่มchangeเหตุการณ์

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

เช่นtriggerไม่มีเหตุการณ์เกิดขึ้น

$cb.prop('checked', !$cb.prop('checked'));

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/5/

เช่นกับtriggerเหตุการณ์การเปลี่ยนแปลงปกติถูกจับ

$cb.prop('checked', !$cb.prop('checked')).trigger('change');

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/6/

หมายเหตุ:

  • อย่าใช้triggerHandlerตามที่แนะนำโดยผู้ใช้รายหนึ่งเนื่องจากจะไม่ทำให้เกิดเหตุการณ์ฟองให้กับตัวจัดการเหตุการณ์ที่มอบหมาย

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/8/

แม้ว่ามันจะทำงานสำหรับตัวจัดการเหตุการณ์เชื่อมต่อโดยตรงกับองค์ประกอบ:

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/9/

เหตุการณ์ที่ถูกเรียกด้วย. triggerHandler () จะไม่ทำให้เกิดลำดับชั้นของ DOM หากองค์ประกอบเป้าหมายไม่ได้รับการจัดการโดยตรงพวกเขาจะไม่ทำอะไรเลย

การอ้างอิง: http://api.jquery.com/triggerhandler/

ถ้าใครมีคุณสมบัติเพิ่มเติมพวกเขารู้สึกว่าจะไม่ได้รับการคุ้มครองโดยการนี้โปรดอย่าแนะนำเพิ่มเติม


31

ใช้วิธีการ 'เปิด' ใหม่ใน jQuery (1.7): http://api.jquery.com/on/

    $('#myform').on('change', 'input[type=checkbox]', function(e) {
        console.log(this.name+' '+this.value+' '+this.checked);

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

1
$("input[name=check1]").prop('checked', true)นี้ไม่ได้ไฟ ดูjsfiddle.net/Z3E8V/2
Peter

7
เพียงเพิ่ม.triggerHandler('change');หลังจากการ.propโทร จากนั้นมันจะสลับกล่องและเรียกใช้เหตุการณ์
ฮันนา


5

ยอมรับความจริงที่ว่าผู้ถามร้องขอ jQuery โดยเฉพาะและคำตอบที่เลือกนั้นถูกต้องควรสังเกตว่าปัญหานี้ไม่จำเป็นต้อง jQuery ต่อพูด หากมีความปรารถนาที่จะแก้ไขปัญหานี้โดยที่ไม่มีใครสามารถตั้งค่าonClickคุณลักษณะของช่องทำเครื่องหมายที่เขาหรือเธอต้องการเพิ่มฟังก์ชันการทำงานเพิ่มเติมเช่น:

HTML:

<form id="myform">
  <input type="checkbox" name="check1" value="check1" onClick="cbChanged(this);">
  <input type="checkbox" name="check2" value="check2" onClick="cbChanged(this);">
</form>

javascript:

function cbChanged(checkboxElem) {
  if (checkboxElem.checked) {
    // Do something special
  } else {
    // Do something else
  }
}

ซอ: http://jsfiddle.net/Y9f66/1/


5
แน่นอนว่าการวางตัวจัดการเหตุการณ์ลงใน HTML นั้นเป็นงานที่แน่นอน แต่มันเป็นความขัดแย้งโดยตรงกับ DRY และวิธีการเพิ่มประสิทธิภาพที่ก้าวหน้า คำตอบที่แม่นยำยิ่งขึ้นคือ "คุณไม่ต้องการ jQuery เพื่อเพิ่มตัวจัดการเหตุการณ์" และใช้ JS มาตรฐานเพื่อแนบตัวจัดการการคลิกในไฟล์ JS แยกต่างหากแทนที่จะวางแอ็ตทริบิวต์ onclick ใน HTML การทำเช่นนี้ "ผลงาน" ดี แต่เขียนโปรแกรมสั่งการปฏิบัติที่คุณควรหลีกเลี่ยงเมื่อเป็นไปได้ (ซึ่งเป็นเกือบตลอดเวลาที่จุดนี้ถ้าคุณจะต้องสนับสนุน IE6 หรือสิ่งซึ่งแม้ MS พูดว่าคุณไม่ควรทำอีกต่อไป)
Carnix

3

ฉันลองใช้รหัสจากคำตอบแรกแล้วมันไม่ทำงาน แต่ฉันได้ลองเล่นและมันใช้ได้กับฉัน

$('#vip').change(function(){
    if ($(this).is(':checked')) {
        alert('checked');
    } else {
        alert('uncheck');
    }
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.