2014-09-29 65 views
0

在我的頁面上,用戶單擊一個元素以編輯它。爲了促進這一點,我將類editable分配給所有這些元素。添加事件監聽器的最佳做法

我應該如何傾聽所有這些元素的點擊?目前,我這樣做:

$lib.addEventListener(document.body, "click", function(event) { 
    if($lib.hasClass(event.target, "editable") { 
    // do stuff 
    } 
}); 

其中$lib是我使用的一個小型的JS庫。

另一種方法是設置一個聽者的每一個元素上,像這樣:

var editables = document.getElementsByClassName("editable"); 
for(var i = 0; i < editables.length; i++) { 
    $lib.addEventListener(editables[i], "click", editElement); 
} 

這在我看來,第一種方式必須是獲得更好的性能,因爲它是唯一一個正在監聽的元素,但是否可以通過將所有這些事件附加到body元素來降低性能?有沒有其他的考慮(例如事件處理的瀏覽器實現),我忽略了哪些建議做第二種方式?

+1

請注意,您的第一個片段不會捕獲任何對您的可編輯元素的子元素的點擊,而第二個片段會執行此操作。 – Bergi 2014-09-29 16:32:39

回答

1

簡短回答:絕對是第一種方式。事件委派的方式性能更高,但需要在代碼中添加額外的條件,所以它基本上是一種複雜性與性能折衷。

較長答案:對於少數元素,添加單個事件處理程序可以正常工作。但是,隨着您添加越來越多的事件處理程序,瀏覽器的性能開始下降。原因是聽事件是內存密集型的。

但是,在DOM中,事件從最具體的目標「冒泡」到最一般的觸發任何事件處理程序。這裏有一個例子:

<html> 
    <body> 
     <div> 
      <a> 
       <img> 
      </a> 
     </div> 
    </body> 
</html> 

如果你點擊了<img>標籤,即點擊事件觸發任何事件處理順序如下:

  1. IMG
  2. 一個
  3. html
  4. document對象

事件代表團是聽父母的一串事件處理程序,而不是關於你所關心的特定元素(比如<img>)的技術(比如<div>)。事件對象將具有一個目標屬性,該屬性指向發生事件的特定dom元素(在本例中爲<img>)。

您的事件委託代碼可能是這個樣子:

$(document).ready(function(){ 
    $('<div>').on('click', function(e) { 
     // check if e.target is an img tag 
     // do whatever in response to the image being clicked 
    }); 
}); 

欲瞭解更多信息,結賬戴夫沃爾什的blog post on Event Delegation或duckduckgo「事件代理」。

注意在OP代碼示例:在第一個例子,target.hasClass('editable')指具體事物點擊必須有一流的可編輯的,如果塊來執行。正如其中一位評論者指出的那樣,這可能不是你想要的。你可能會想嘗試這些方針的東西來代替:

$(document).on('click', function(e) { 
    if ($(e.target).parents(".editable").length) { 
     // Do whatever 
    } 
}); 

讓我們打破了一點:

  • $(e.target) - 任何的是被點擊轉化爲jQuery的
  • .parents(".editable")在頁面上 - 尋找元素的所有祖先點擊,然後過濾到只包括類「可編輯」的
  • .length - 這應該是一個整數。如果爲0,則表示沒有「可修改」類別的父母
+0

感謝您提供非常詳細的答案。 – 2014-09-29 19:18:04