簡體   English   中英

jQuery .on() 委托與匹配嵌套元素的選擇器

[英]jQuery .on() delegation with selector that matches nested elements

 // Example A $("#delegate").on("click", function(event) { // executes on click on any descendant of #delegate or self (not a delegate at all) // 'this' is #delegate }); // Example B $("#delegate").on("click", "#outer", function(event) { // executes on click on any descendant of #outer or self // 'this' is #outer or #inner (depends on the actual click) }); $("#delegate").on("click", "#inner", function(event) { // executes on click on any descendant of #inner or self (nothing happens when clicking #outer) // 'this' is #inner }); // Example C (now it's getting weird) $("#delegate").on("click", "div", function(event) { // executes twice, when clicking #inner, because the event passes #outer when bubbling up // one time 'this' is #inner, and the other time 'this' is #outer // stopPropagation() // actually prevents the second execution });
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="delegate"> <div id="outer"> outer <div id="inner"> inner </div> </div> </div>

你如何從邏輯上解釋這種行為?

只有一個點擊事件,從#inner開始,通過#outer ,最后到達#delegate

該事件由#delegate的 on-handler #delegate (恰好)一次。 處理程序檢查事件的歷史記錄是否包含任何 div 元素。

如果這適用,回調函數應該被調用一次。 這就是我所期望的。 “單個事件、單個處理程序、單個條件、單個回調”。

如果您查看stopPropagation()行為,它會變得更加瘋狂。 您實際上可以避免第二次執行,盡管事件已經到達#delegate stopPropagation(不應該在這里工作。

在委托邏輯的實現中做了什么樣的“魔法”? 事件冒泡和程序流是否以任何方式分開?

請不要首先發布“實用建議”(“請改用 xyz!”)。 我想了解為什么代碼的工作方式如此。

由於您以兩種方式在所有 div 上綁定事件:

  1. 使用元素 div 的 id 屬性。
  2. 使用元素 div 的標簽名稱。

所以如果你event.stopPropagation(); 在最后一個警報仍然會出現兩次,因為您點擊了 div 和#inner (例如)。

檢查下面的片段。

 $("#delegate").on("click", function(event) { alert(this.id); }); /* $("#delegate").on('click', "#outer", function(event) { alert(this.id); }); $("#delegate").on('click', "#inner", function(event) { alert(this.id); }); */ // now it's getting weird $("#delegate").on("click", "div", function(event) { event.stopPropagation(); alert(this.id); });
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="delegate"> <div id="outer"> outer <div id="inner"> inner </div> </div> </div>

事件委托的工作方式是 jQuery 從最里面的目標到委托綁定的元素沿着 DOM 樹向上走,測試每個元素以查看它是否與選擇器匹配。 如果是,則執行將this綁定到該元素的處理程序。

event.stopPropagation被調用時,它會在event對象中設置一個標志。 遍歷 DOM 樹的循環也調用event.isPropagationStopped() 如果傳播停止,它就會跳出循環。

換句話說,jQuery 在實現委托時正在做自己的冒泡和傳播停止,它沒有利用瀏覽器的冒泡(除了這種冒泡是在#delegate上觸發初始事件所#delegate ,因此 jQuery 循環將跑)。

一切都按預期工作。 看看這個小提琴

$("#delegate").on("click", "div", function(event) {
  // event.stopPropagation();
  alert('div: ' + $(this).attr('id'));
});

單擊#inner將觸發上述事件。 該事件將氣泡高達#outer因為#inner是的后代#outer 由於#outer也是一個<div ,事件也將在#outer#outer 從邏輯上講,點擊#inner將首先提示“div:inner”,然后是“div:outer”。

調用event.stopPropagation()告訴事件不要冒泡,因此#outer保持未#outer狀態。

除了這個小提琴

<div id="delegate">
  <div id="first">
    first
  </div>
  <div id="second">
    second
      <div id="third">
        third, inside second
      </div>
    </div>
</div>

點擊第三個將首先提醒third ,然后second然后停止,因為#first不是父級而是兄弟級。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM