jQuery: มีตัวจัดการมากกว่าหนึ่งตัวสำหรับเหตุการณ์เดียวกัน


137

จะเกิดอะไรขึ้นถ้าฉันผูกตัวจัดการเหตุการณ์สองตัวกับเหตุการณ์เดียวกันสำหรับองค์ประกอบเดียวกัน

ตัวอย่างเช่น:

var elem = $("...")
elem.click(...);
elem.click(...);

ตัวจัดการล่าสุด "ชนะ" หรือตัวจัดการทั้งสองจะทำงานหรือไม่

คำตอบ:


168

ตัวจัดการทั้งสองจะทำงานรูปแบบเหตุการณ์ jQuery อนุญาตให้มีหลายตัวจัดการในองค์ประกอบเดียวดังนั้นตัวจัดการในภายหลังจะไม่แทนที่ตัวจัดการรุ่นเก่า

ตัวจัดการจะดำเนินการในลำดับที่พวกเขาถูกผูกไว้


1
เกิดอะไรขึ้นกับวิธีการของพื้นเมือง? และชาวพื้นเมืองรู้ได้อย่างไรว่าจะลบสิ่งที่เฉพาะเจาะจงได้อย่างไร
SuperUberDuper

1
ตาม DOM ระดับ 3 (อ้างอิงข้อมูลจำเพาะ HTML 5) ตัวจัดการเหตุการณ์จะดำเนินการตามลำดับที่ลงทะเบียน - w3.org/TR/DOM-Level-3-Events/#event-phaseและw3.org/TR/ 2014 / REC-html5-20141028 / ... ตัวจัดการเหตุการณ์สามารถลบออกได้โดยผ่านการอ้างอิงไปยังตัวจัดการที่ลงทะเบียนแล้ว
Russ Cam

@RussCam จะเกิดอะไรขึ้นถ้าตัวจัดการเดียวกันถูกผูกไว้มากกว่าเดิมอีกครั้งหนึ่งให้บอกว่าjQuery('.btn').on('click',handlerClick);ถูกเรียกในสถานที่ต่าง ๆ โดยที่ไม่ได้.offมีอยู่จริง
techie_28

โปรดทราบว่าสำหรับวิดเจ็ต jQueryUI widgetfactory สิ่งนี้ไม่เป็นความจริงหากคุณตั้งค่าตัวจัดการเป็นตัวเลือก สำหรับการเรียกใช้ตัวจัดการทั้งเก่าและใหม่คุณต้องใช้bindวิธีการ ดูรายละเอียดนี้ได้ที่: learn.jquery.com/jquery-ui/widget-factory/ ......
Michael Scheper

@MichaelScheper รู้สึกอิสระที่จะแก้ไขคำตอบและอัปเดตข้อมูลเพิ่มเติม
Russ Cam

36

สมมติว่าคุณมีตัวจัดการสองตัวคือfและgและต้องการตรวจสอบให้แน่ใจว่าพวกมันจะถูกดำเนินการในลำดับที่เป็นที่รู้จักและแน่นอนจากนั้นเพียงแค่แค็ปซูล:

$("...").click(function(event){
  f(event);
  g(event);
});

ด้วยวิธีนี้มี (จากมุมมองของ jQuery) เพียงหนึ่งตัวจัดการซึ่งเรียกfและgในลำดับที่ระบุ


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

คอลเลกชันของตัวจัดการที่มีลำดับจะถูกกำหนดโดยทางโปรแกรม
Aaron Blenkush

17

jQuery's .bind () ยิงตามลำดับที่ถูกผูกไว้ :

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

ที่มา: http://api.jquery.com/bind/

เนื่องจากฟังก์ชั่นอื่น ๆ ของ jQuery (เช่น.click()) เป็นทางลัดสำหรับ.bind('click', handler)ฉันจะเดาได้ว่าพวกมันจะถูกเรียกตามลำดับที่ถูกผูกไว้


11

คุณควรจะสามารถใช้การโยงเพื่อดำเนินกิจกรรมตามลำดับเช่น:

$('#target')
  .bind('click',function(event) {
    alert('Hello!');
  })
  .bind('click',function(event) {
    alert('Hello again!');
  })
  .bind('click',function(event) {
    alert('Hello yet again!');
  });

ฉันเดาว่าโค้ดด้านล่างทำเช่นเดียวกัน

$('#target')
      .click(function(event) {
        alert('Hello!');
      })
      .click(function(event) {
        alert('Hello again!');
      })
      .click(function(event) {
        alert('Hello yet again!');
      });

ที่มา: http://www.peachpit.com/articles/article.aspx?p=1371947&seqNum=3

TFMยังพูดว่า:

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


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

ehh? สิ่งที่เกี่ยวกับ "ตอนนี้เมื่อเหตุการณ์คลิกเกิดขึ้นตัวจัดการเหตุการณ์แรกจะถูกเรียกตามด้วยตัวที่สองตามด้วยตัวที่สาม" ไม่ชัดเจน?
anddoutoi

และใช่ฉันรู้ว่า recs อย่างเป็นทางการไม่ได้กำหนดสิ่งนี้และ PPK ได้พิสูจน์แล้วว่าการดำเนินการเหตุการณ์เป็นแบบสุ่ม แต่บางที jQuery ได้แก้ไขสิ่งนี้ ^^
anddoutoi

อ่าพลาดประโยคนั้นไป ในความเป็นจริงผู้เขียนมีข้อมูลที่ผิด jQuery ยังไม่ได้ "แก้ไข" สิ่งนี้ เนื่องจากข้อมูลจำเพาะไม่ได้กำหนดคำสั่งอย่างเป็นทางการจึงไม่มีความจำเป็นต้องแก้ไขทางเทคนิค
Crescent Fresh

5
@CrescentFresh: ขออภัยสำหรับการตอบกลับล่าช้าฉันเพิ่งเห็นคำถาม แต่ฉันต้องการให้คุณชี้ไปที่ลิงค์มันเป็นเอกสารอย่างเป็นทางการของ jQuery และชัดเจนว่าWhen an event reaches an element, all handlers bound to that event type for the element are fired. If there are multiple handlers registered, they will always execute in the order in which they were bound. After all handlers have executed, the event continues along the normal event propagation path.
Razort4x

2

ตัวจัดการทั้งสองจะถูกเรียก

คุณอาจกำลังคิดถึงการโยงเหตุการณ์แบบอินไลน์ (เช่น"onclick=...") ซึ่งข้อเสียเปรียบครั้งใหญ่เป็นเพียงตัวจัดการเดียวเท่านั้นที่อาจถูกตั้งค่าไว้สำหรับเหตุการณ์

jQuery เป็นไปตามรูปแบบการลงทะเบียนเหตุการณ์ DOM ระดับ 2 :

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


@ Rich: คำสั่งซื้อไม่ได้ถูกกำหนดอย่างเป็นทางการ
Crescent Fresh

2

ทำให้การทำงานสำเร็จเป็นผลสำเร็จโดยใช้วิธีการ 2 วิธี: การห่อหุ้มของ Stephan202 และผู้ฟังเหตุการณ์หลายรายการ ฉันมี 3 แท็บการค้นหาลองกำหนด id ของพวกเขาใน Array:

var ids = new Array("searchtab1", "searchtab2", "searchtab3");

เมื่อเนื้อหาของ searchtab1 เปลี่ยนไปฉันต้องการอัปเดต searchtab2 และ searchtab3 มันเป็นวิธีการห่อหุ้ม:

for (var i in ids) {
    $("#" + ids[i]).change(function() {
        for (var j in ids) {
            if (this != ids[j]) {
                $("#" + ids[j]).val($(this).val());
            }
        }
    });
}

ผู้ฟังเหตุการณ์หลายรายการ:

for (var i in ids) {
    for (var j in ids) {
        if (ids[i] != ids[j]) {
            $("#" + ids[i]).change(function() {
                $("#" + ids[j]).val($(this).val());
            });
        }
    }
}

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


1

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

อาจจะดิบ แต่มันควรจะใช้ได้แน่นอน


0

jquery จะดำเนินการตัวจัดการทั้งสองเพราะมันช่วยให้หลายตัวจัดการเหตุการณ์ ฉันได้สร้างรหัสตัวอย่าง คุณสามารถลอง

การสาธิต

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