เหตุการณ์ jQuery ทั้งหมดควรผูกติดกับ $ (เอกสาร) หรือไม่


164

สิ่งนี้มาจากไหน

เมื่อฉันเรียนรู้ jQuery ครั้งแรกปกติฉันจะแนบกิจกรรมดังนี้

$('.my-widget a').click(function() {
    $(this).toggleClass('active');
});

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

$('.my-widget').on('click','a',function() {
    $(this).toggleClass('active');
});

นี่เป็นวิธีที่แนะนำในการทำซ้ำพฤติกรรมของกิจกรรม. live () ที่เลิกใช้แล้ว ซึ่งเป็นสิ่งสำคัญสำหรับฉันเนื่องจากมีไซต์ของฉันเพิ่ม / ลบวิดเจ็ตอยู่ตลอดเวลา ข้างต้นไม่ได้ทำงานเหมือนกับ. live () เนื่องจากองค์ประกอบเท่านั้นที่ถูกเพิ่มลงในคอนเทนเนอร์ที่มีอยู่แล้ว '.my-widget' จะได้รับพฤติกรรม หากฉันเพิ่มบล็อก html แบบไดนามิกอีกครั้งหลังจากที่โค้ดนั้นรันองค์ประกอบเหล่านั้นจะไม่ทำให้เกิดเหตุการณ์ที่เกี่ยวข้อง แบบนี้:

setTimeout(function() {
    $('body').append('<div class="my-widget"><a>Click does nothing</a></div>');
}, 1000);


สิ่งที่ฉันต้องการบรรลุ:

  1. พฤติกรรมเก่าของ. live () // หมายถึงการแนบเหตุการณ์ไปยังองค์ประกอบที่ยังไม่มีอยู่
  2. ประโยชน์ของ. on ()
  3. ประสิทธิภาพที่เร็วที่สุดในการเชื่อมโยงเหตุการณ์
  4. วิธีง่ายๆในการจัดการกิจกรรม

ตอนนี้ฉันแนบกิจกรรมทั้งหมดเช่นนี้:

$(document).on('click.my-widget-namespace', '.my-widget a', function() {
    $(this).toggleClass('active');
});

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

โซลูชัน / คำถามของฉัน

ดังนั้นฉันเริ่มคิดว่าเหตุการณ์ jQuery ควรถูกผูกไว้กับ $ (เอกสาร) เสมอ
มีเหตุผลใดที่คุณไม่ต้องการทำเช่นนี้?
นี่ถือว่าเป็นแนวปฏิบัติที่ดีที่สุดหรือไม่? ถ้าไม่ทำไม

หากคุณอ่านทั้งหมดนี้แล้วขอบคุณ ฉันขอขอบคุณข้อเสนอแนะ / ข้อมูลเชิงลึกใด ๆ / ทั้งหมด

สมมติฐาน:

  1. ใช้ jQuery ที่รองรับ.on()// อย่างน้อยเวอร์ชั่น 1.7
  2. คุณต้องการเพิ่มเหตุการณ์ให้กับเนื้อหาที่เพิ่มแบบไดนามิก

อ่าน / ตัวอย่าง:

  1. http://24ways.org/2011/your-jquery-now-with-less-suck
  2. http://brandonaaron.net/blog/2010/03/4/event-delegation-with-jquery
  3. http://www.jasonbuckboyer.com/playground/speed/speed.html
  4. http://api.jquery.com/on/

คำตอบ:


215

ไม่ - คุณไม่ควรผูกตัวจัดการเหตุการณ์ที่ได้รับมอบหมายทั้งหมดเข้ากับdocumentวัตถุ นั่นอาจเป็นสถานการณ์ที่เลวร้ายที่สุดที่คุณสามารถสร้างได้

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

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

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

นี่คือบางครั้งเมื่อจำเป็นต้องมีการมอบหมายเหตุการณ์หรือเป็นประโยชน์:

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

เพื่อทำความเข้าใจนี้อีกเล็กน้อยหนึ่งต้องเข้าใจว่า jQuery มอบหมายเหตุการณ์จัดการ เมื่อคุณเรียกสิ่งนี้:

$("#myParent").on('click', 'button.actionButton', myFn);

มันจะติดตั้งตัวจัดการเหตุการณ์ jQuery ทั่วไปบน#myParentวัตถุ เมื่อเหตุการณ์คลิกมีฟองอากาศมากถึงตัวจัดการเหตุการณ์ที่ได้รับมอบหมายนี้ jQuery จะต้องผ่านรายการตัวจัดการเหตุการณ์ที่ได้รับมอบหมายที่แนบมากับวัตถุนี้และดูว่าองค์ประกอบต้นทางสำหรับเหตุการณ์ตรงกับตัวเลือกใด ๆ ในตัวจัดการเหตุการณ์ที่ได้รับมอบหมาย

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

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


ดังนั้นเพื่อให้ได้ประสิทธิภาพที่ดีที่สุด:

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

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

ก็อยากจะบอกว่าคุณเชื่อฉัน - อย่าผูกเหตุการณ์ทั้งหมดไว้ที่ $ (เอกสาร) เชื่อมโยงกับพาเรนต์ที่ไม่มีการเปลี่ยนแปลงที่ใกล้เคียงที่สุดเท่าที่จะทำได้ ฉันเดาว่าฉันยังต้องตัดสินใจเป็นกรณี ๆ ไปเมื่อการมอบหมายเหตุการณ์ดีกว่าการเชื่อมโยงเหตุการณ์กับองค์ประกอบโดยตรง และเมื่อฉันต้องการกิจกรรมที่เชื่อมโยงกับเนื้อหาแบบไดนามิก (ที่ไม่มีพ่อแม่ที่ไม่เปลี่ยนแปลง) ฉันเดาว่าฉันจะทำในสิ่งที่ @Vega แนะนำด้านล่างและเพียงแค่ "ผูก handler (s) หลังจากที่เนื้อหาถูกแทรกเข้าไป ( ) DOM "โดยใช้พารามิเตอร์บริบทของ jQuery ในตัวเลือกของฉัน
บั๊ก

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

คุณสมบูรณ์แบบ. เห็นด้วยอย่างสิ้นเชิง! ฉันเข้าใจว่านี่เป็นสิ่งที่เลวร้ายที่สุดที่ฉันสามารถทำได้ - $(document).on('click', '[myCustomAttr]', function () { ... });?
Artem Fitiskin

การใช้ pjax / turbolinks ก่อให้เกิดปัญหาที่น่าสนใจเนื่องจากองค์ประกอบทั้งหมดถูกสร้าง / ลบแบบไดนามิก (นอกเหนือจากการโหลดหน้าแรก) ดังนั้นจึงเป็นการดีที่จะผูกทุกเหตุการณ์ครั้งเพื่อdocument, หรือผูกกับการเลือกเฉพาะเจาะจงมากขึ้นบนpage:loadและเหตุการณ์เหล่านี้ยกเลิกการเชื่อมโยงในpage:after-remove? Hmmm
Dom Christie

9

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

คุณควรใช้การมอบหมายกิจกรรมเมื่อใด

  1. เมื่อคุณผูกตัวจัดการทั่วไปสำหรับองค์ประกอบเพิ่มเติมที่ต้องการฟังก์ชั่นเดียวกัน (เช่น: โฮเวอร์แถวของตาราง)
    • ในตัวอย่างถ้าคุณต้องผูกทุกแถวโดยใช้การเชื่อมโดยตรงคุณจะต้องสร้าง n handler สำหรับ n row ในตารางนั้น โดยใช้วิธีการมอบหมายคุณสามารถจัดการทั้งหมดใน 1 ตัวจัดการง่าย ๆ
  2. เมื่อคุณเพิ่มเนื้อหาแบบไดนามิกบ่อยครั้งใน DOM (เช่น: เพิ่ม / ลบแถวออกจากตาราง)

ทำไมคุณไม่ควรใช้การมอบหมายกิจกรรม?

  1. การมอบหมายกิจกรรมช้าลงเมื่อเปรียบเทียบกับการผูกกิจกรรมโดยตรงกับองค์ประกอบ
    • มันเปรียบเทียบตัวเลือกเป้าหมายในทุกฟองที่พบการเปรียบเทียบจะมีราคาแพงตามที่ซับซ้อน
  2. ไม่มีการควบคุมเหตุการณ์ที่เดือดปุด ๆ จนกว่าจะกระทบองค์ประกอบที่ถูกผูกไว้

PS:แม้สำหรับเนื้อหาแบบไดนามิกคุณไม่จำเป็นต้องใช้วิธีการมอบหมายกิจกรรมหากคุณผูกตัวจัดการหลังจากที่เนื้อหาถูกแทรกลงใน DOM (หากมีการเพิ่มเนื้อหาแบบไดนามิกไม่ได้ถูกลบ / เพิ่มซ้ำบ่อย)


0

เห็นได้ชัดว่าการมอบหมายเหตุการณ์จริง ๆ แล้วแนะนำตอนนี้ อย่างน้อยสำหรับวานิลลา js

https://gomakethings.com/why-event-delegation-is-a-better-way-to-listen-for-events-in-vanilla-js/

"ประสิทธิภาพของเว็บ # รู้สึกว่าการฟังทุกการคลิกในเอกสารจะไม่ดีต่อประสิทธิภาพ แต่จริงๆแล้วมันมีประสิทธิภาพมากกว่าการมีกลุ่มผู้ฟังเหตุการณ์ในแต่ละรายการ"


0

ฉันต้องการเพิ่มข้อสังเกตและการโต้เถียงเพื่อคำตอบของ jfriend00 (ส่วนใหญ่เป็นเพียงความคิดเห็นของฉันตามความรู้สึกของฉัน)

ไม่ - คุณไม่ควรผูกตัวจัดการเหตุการณ์ที่ได้รับมอบหมายทั้งหมดเข้ากับวัตถุเอกสาร นั่นอาจเป็นสถานการณ์ที่เลวร้ายที่สุดที่คุณสามารถสร้างได้

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

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

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

ฉันเห็นด้วยกับเรื่องนี้ หากคุณแน่ใจ 100% ว่าเหตุการณ์จะเกิดขึ้นภายในคอนเทนเนอร์มันจะผูกมัดเหตุการณ์ไว้ในคอนเทนเนอร์นี้ แต่ฉันจะยังคงโต้แย้งกับการเชื่อมโยงเหตุการณ์กับองค์ประกอบทริกเกอร์โดยตรง

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

นี้เป็นเพียงไม่เป็นความจริง. โปรดดูรหัสนี้เพ็ญ: https://codepen.io/pwkip/pen/jObGmjq

document.addEventListener('keypress', (e) => {
    e.preventDefault();
});

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

นี่คือบางครั้งเมื่อจำเป็นต้องมีการมอบหมายเหตุการณ์หรือเป็นประโยชน์:

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

ฉันต้องการตอบด้วยข้อความนี้จากhttps://ehsangazar.com/optimizing-javascript-event-listeners-for-performance-e28406ad406c

Event delegation promotes binding as few DOM event handlers as possible, since each event handler requires memory. For example, let’s say that we have an HTML unordered list we want to bind event handlers to. Instead of binding a click event handler for each list item (which may be hundreds for all we know), we bind one click handler to the parent unordered list itself.

นอกจากนี้ googling สำหรับperformance cost of event delegation googleส่งคืนผลลัพธ์มากขึ้นในความโปรดปรานของการมอบหมายเหตุการณ์

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

$ ("# myParent"). on ('คลิก', 'button.actionButton', myFn); มันจะติดตั้งตัวจัดการเหตุการณ์ jQuery ทั่วไปบนวัตถุ #myParent เมื่อเหตุการณ์คลิกมีฟองอากาศมากถึงตัวจัดการเหตุการณ์ที่ได้รับมอบหมายนี้ jQuery จะต้องผ่านรายการตัวจัดการเหตุการณ์ที่ได้รับมอบหมายที่แนบมากับวัตถุนี้และดูว่าองค์ประกอบต้นทางสำหรับเหตุการณ์ตรงกับตัวเลือกใด ๆ ในตัวจัดการเหตุการณ์ที่ได้รับมอบหมาย

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

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

เอกสารนี้อยู่ที่ไหน หากเป็นเรื่องจริง jQuery ดูเหมือนจะจัดการกับการมอบหมายในวิธีที่ไม่มีประสิทธิภาพมากและจากนั้นข้อโต้แย้งของฉันควรจะใช้กับวานิลลา JS เท่านั้น

ยัง: ฉันต้องการหาแหล่งที่เป็นทางการที่สนับสนุนการเรียกร้องนี้

:: แก้ไข ::

ดูเหมือนว่า jQuery กำลังทำเหตุการณ์เดือดปุด ๆ อย่างไม่มีประสิทธิภาพ (เพราะรองรับ IE8) https://api.jquery.com/on/#event-performance

ดังนั้นข้อโต้แย้งของฉันที่นี่ส่วนใหญ่ถือเป็นจริงสำหรับวานิลลา JS และเบราว์เซอร์ที่ทันสมัย

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