2014-09-29 85 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