javascript - jQuery .live() กับ .on() วิธีสำหรับการเพิ่มเหตุการณ์คลิกหลังจากโหลด HTML แบบไดนามิก
ฉันกำลังใช้ jQuery เวอร์ชัน 1.7.1 ซึ่งวิธีการ .live() ดูเหมือนว่าจะถูกเลิกใช้แล้ว
ปัญหาที่ฉันกำลังเจอคือเมื่อโหลด HTML แบบไดนามิกเข้าสู่ element โดยใช้:
$('#parent').load("http://...");
ถ้าฉันพยายามเพิ่มเหตุการณ์คลิกทีหลัง มันจะไม่ลงทะเบียนเหตุการณ์โดยใช้วิธีใดวิธีหนึ่งเหล่านี้
$('#parent').click(function() ...);
หรือ
// according to documentation this should be used instead of .live()
$('#child').on('click', function() ...);
วิธีที่ถูกต้องในการทำให้ฟังก์ชันนี้ทำงานคืออะไร? สำหรับผมดูเหมือนว่าจะทำงานได้แค่กับ .live() แต่ผมไม่ควรใช้วิธีนั้น โปรดทราบว่า #child เป็นองค์ประกอบที่โหลดแบบไดนามิก
ขอบคุณ
คำตอบ #1
ถ้าคุณต้องการให้ตัวจัดการการคลิกทำงานบนองค์ประกอบที่ถูกโหลดแบบไดนามิก คุณก็ต้องตั้งตัวจัดการเหตุการณ์บนวัตถุพ่อแม่ (ที่ไม่ได้ถูกโหลดแบบไดนามิก) และให้ตัวเลือกที่ตรงกับวัตถุแบบไดนามิกของคุณดังนี้:
$('#parent').on("click", "#child", function() {});
ตัวจัดการเหตุการณ์จะถูกแนบกับวัตถุ #parent และทุกครั้งที่เหตุการณ์คลิกเกิดขึ้นและไหลขึ้นไปถึงมันซึ่งเกิดจาก #child มันจะเรียกใช้ตัวจัดการคลิกของคุณ สิ่งนี้เรียกว่าการจัดการเหตุการณ์แบบมอบหมาย (การจัดการเหตุการณ์ถูกมอบหมายให้กับวัตถุพ่อแม่)
มันทำในลักษณะนี้เพราะคุณสามารถแนบเหตุการณ์ไปยังวัตถุ #parent ได้แม้ว่าวัตถุ #child ยังไม่มีอยู่ แต่เมื่อมันปรากฏขึ้นในภายหลังและถูกคลิก เหตุการณ์คลิกจะถูกส่งขึ้นไปยังวัตถุ #parent ซึ่งจะเห็นว่ามันเริ่มต้นจาก #child และมีตัวจัดการเหตุการณ์สำหรับคลิกบน #child และเรียกใช้งานเหตุการณ์ของคุณ
คำตอบ #2
ลองอันนี้:
$('#parent').on('click', '#child', function() {
// Code
});
จากเอกสาร $.on():
ตัวจัดการเหตุการณ์จะถูกผูกเฉพาะกับองค์ประกอบที่ถูกเลือกในปัจจุบันเท่านั้น; พวกมันต้องมีอยู่บนหน้าในขณะที่โค้ดของคุณเรียกใช้
.on()
องค์ประกอบ #child ของคุณไม่มีอยู่เมื่อคุณเรียก $.on() ดังนั้นเหตุการณ์จึงไม่ถูกผูกไว้ (ซึ่งแตกต่างจาก $.live()) อย่างไรก็ตาม #parent มีอยู่จริง ดังนั้นการผูกมัดเหตุการณ์กับสิ่งนั้นจึงเป็นเรื่องปกติ
อาร์กิวเมนต์ตัวที่สองในโค้ดของฉันด้านบนทำหน้าที่เป็น 'ตัวกรอง' เพื่อให้ทำงานก็ต่อเมื่อเหตุการณ์ฟองขึ้นมาตรง #parent จาก #child เท่านั้น
คำตอบ #3
$(document).on('click', '.selector', function() { /* do stuff */ });แก้ไข: ฉันกำลังให้ข้อมูลเพิ่มเติมเกี่ยวกับวิธีการทำงานของสิ่งนี้ เพราะ... คำต่างๆ ด้วยตัวอย่างนี้ คุณกำลังวางตัวฟังเหตุการณ์บนเอกสารทั้งหมด
เมื่อคุณ คลิก ที่องค์ประกอบใด ๆ ที่ตรงกับ .selector เหตุการณ์จะเลื่อนขึ้นไปยังเอกสารหลัก -- ตราบใดที่ไม่มีผู้ฟังอื่นที่เรียกใช้วิธี event.stopPropagation() -- ซึ่งจะหยุดการเลื่อนขึ้นของเหตุการณ์ไปยังองค์ประกอบหลัก
แทนที่จะผูกกับองค์ประกอบเฉพาะหรือชุดขององค์ประกอบ คุณกำลังฟังเหตุการณ์ใด ๆ ที่มาจากองค์ประกอบที่ตรงกับตัวคัดเลือกที่ระบุ ซึ่งหมายความว่าคุณสามารถสร้างตัวฟังเพียงตัวหนึ่ง ครั้งเดียว ที่จะตรงกับองค์ประกอบที่มีอยู่ปัจจุบันรวมถึงองค์ประกอบที่เพิ่มขึ้นแบบไดนามิกได้โดยอัตโนมัติ
นี่ฉลาดด้วยหลายเหตุผล รวมถึงประสิทธิภาพและการใช้หน่วยความจำ (ในแอปพลิเคชันขนาดใหญ่)
แก้ไข :
ชัดเจนว่า แพเรนต์อิลิเมนต์ที่ใกล้ที่สุดที่คุณสามารถฟังเหตุการณ์ได้จะดีกว่า และคุณสามารถใช้เอลิเมนต์ใดก็ได้แทน document ตราบใดที่ลูกที่คุณต้องการตรวจสอบเหตุการณ์อยู่ภายในแพเรนต์อิลิเมนต์นั้น... แต่สิ่งนั้นจริง ๆ แล้วไม่มีอะไรเกี่ยวข้องกับคำถาม
คำตอบ #4
สิ่งที่เทียบเท่ากับ .live() ในเวอร์ชัน 1.7 จะเป็นดังนี้:
$(document).on('click', '#child', function() ...);
พื้นฐานแล้ว ให้สังเกตเอกสารสำหรับเหตุการณ์การคลิกและกรองเหตุการณ์เหล่านั้นสำหรับ #child
คำตอบ #5
ฉันรู้ว่ามันอาจจะตอบช้าไปหน่อย แต่ฉันได้สร้าง polyfill สำหรับเมธอด .live() ขึ้นมาแล้ว ฉันได้ทดสอบมันใน jQuery 1.11 และมันดูเหมือนจะทำงานได้ค่อนข้างดี ฉันรู้ว่าเราควรใช้เมธอด .on() ทุกที่เท่าที่เป็นไปได้ แต่ในโครงการใหญ่ ๆ ที่ไม่สามารถเปลี่ยนการเรียกใช้ .live() ทั้งหมดเป็น .on() ได้ด้วยเหตุผลใดก็ตาม ข้างล่างนี้อาจใช้ได้
if(jQuery && !jQuery.fn.live) {
jQuery.fn.live = function(evt, func) {
$('body').on(evt, this.selector, func);
}
}
เพียงรวมไว้หลังจากที่คุณโหลด jQuery และก่อนที่คุณจะเรียก live()
