在何处添加事件侦听器的最佳实践 [英] Best practices for where to add event listeners

查看:55
本文介绍了在何处添加事件侦听器的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的页面上,用户单击元素以对其进行编辑.为了方便起见,我将 editable 类分配给所有此类元素.

On my page, the user clicks on an element in order to edit it. To facilitate this, I assign the class editable to all such elements.

我应该如何监听所有这些元素的点击?目前,我正在这样做:

How should I listen for clicks on all these elements? Currently, I'm doing this:

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

其中 $ lib 是我使用的一个小型JS库.

where $lib is a little JS library I use.

替代方法是在每个元素上设置一个侦听器,如下所示:

The alternative would be to set a listener on every element, like this:

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

在我看来,第一种方法必须对性能更好,因为它只是被监听的一个元素,但是是否可以通过将所有此类事件附加到body元素来降低性能?我是否忽略了其他考虑因素(例如,事件处理的浏览器实现),因此建议采用第二种方法进行处理?

It seems to me that the first way must be better for performance, since it's only one element being listened on, but is it possible to degrade performance by attaching all such events to the body element? Are there any other considerations (e.g. browser implementations of event handling) that I'm neglecting which would suggest doing it the second way?

推荐答案

简短的回答:肯定是第一种方法.事件委托的性能更高,但是在代码中需要额外的条件,因此从本质上来说,这是复杂性与性能之间的权衡.

Short answer: definitely do it the first way. Event delegation is way more performant, but requires extra conditionals in your code, so it's basically a complexity versus performance tradeoff.

更长的答案:对于少数元素,添加单个事件处理程序效果很好.但是,随着您添加越来越多的事件处理程序,浏览器的性能开始下降.原因是侦听事件会占用大量内存.

Longer Answer: For a small number of elements, adding individual event handlers works fine. However, as you add more and more event handlers, the browser's performance begins to degrade. The reason is that listening for events is memory intensive.

但是,在DOM中,事件从最具体的目标冒泡"到最一般的事件,从而触发了所有事件处理程序.这是一个示例:

However, in the DOM, events "bubble up" from the most specific target to the most general triggering any event handlers along the way. Here's an example:

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

如果您单击< img> 标记,则该click事件将按以下顺序触发所有事件处理程序:

If you clicked on the <img> tag, that click event would fire any event handlers in this order:

  1. img
  2. a
  3. div
  4. 身体
  5. html
  6. 文档对象

事件委托是一种侦听父级(例如< div> )的事件处理程序的技术,而不是您关心的特定元素(例如< img> ).事件对象将具有目标属性,该目标属性指向事件所源自的特定dom元素(在本例中为< img> ).

Event delegation is the technique of listening to a parent (say <div>) for a bunch of event handlers instead of the specific element you care about (say <img>). The event object will have a target property which points to the specific dom element from which the event originated (in this case <img>).

您用于事件委派的代码可能看起来像这样:

Your code for event delegation might look something like this:

$(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
    });
});

有关更多信息,请查看戴夫·沃尔什(Dave Walsh)的关于事件委托的博客帖子或duckduckgo事件委托".

For more information checkout Dave Walsh's blog post on Event Delegation or duckduckgo "event delegation".

在OP中注意代码示例:在第一个示例中, target.hasClass('editable')意味着单击的特定内容必须具有可编辑的类.要执行的if块.正如一位评论者指出的那样,这可能不是您想要的.您可能想尝试以下方法:

NOTE ON CODE SAMPLE IN OP: In the first example, target.hasClass('editable') means that the specific thing clicked on must have the class editable for the if block to execute. As one of the commenters pointed out, that's probably not what you want. You might want to try something along these lines instead:

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

让我们细分一下:

  • $(e.target)-点击页面上的所有内容都转换为jQuery
  • .parents(.editable")-查找所单击元素的所有祖先,然后过滤以仅包含"editable"类的祖先.
  • .length -这应该是一个整数.如果为0,则表示没有可编辑"课程的父母
  • $(e.target) - anything that on the page that was clicked converted to jQuery
  • .parents(".editable") - find all the ancestors of the element clicked, then filter to only include ones with the class "editable"
  • .length - this should be an integer. If 0, this means there are no parents with "editable" class

这篇关于在何处添加事件侦听器的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆