这是从哪里来的

当我第一次学习jQuery时,我通常会附加以下事件:

$('.my-widget a').click(function() {
    $(this).toggleClass('active');
});

在了解了更多关于 Select 器速度和事件委派的信息后,我在几个地方读到了"jQuery事件委派将使代码更快"所以我开始写这样的代码:

$('.my-widget').on('click','a',function() {
    $(this).toggleClass('active');
});

这也是复制已弃用的.live()事件的行为的推荐方式.这对我来说很重要,因为我的很多站点一直在动态添加/删除小部件.不过,上面的行为并不完全像.live(),因为只有添加到现有容器‘.my-widget’中的元素才会获得该行为.如果我在代码运行后动态添加另一个HTML挡路,这些元素将不会获得绑定到它们的事件.如下所示:

setTimeout(function() {
    $('body').append('<div class="my-widget"><a>Click does nothing</a></div>');
}, 1000);


What I want to achieve:

  1. 旧的行为.live()//表示将事件附加到尚未存在的元素
  2. the benefits of .on()
  3. 绑定事件的最快性能
  4. 管理事件的简单方法

我现在附上所有这样的事件:

$(document).on('click.my-widget-namespace', '.my-widget a', function() {
    $(this).toggleClass('active');
});

Which seems to meet all my goals. (Yes it's slower in IE for some reason, no idea why?) It's fast because only a single event is tied to a singular element and the secondary selector is only evaluated when the event occurs (please correct me if this is wrong here). The namespace is awesome since it makes it easier to toggle the event listener.

My Solution/Question

So I'm starting to think that jQuery events should always be bound to $(document).
Is there any reason why you would not want to do this?
Could this be considered a best practice? If not, why?

如果你读过这整件事,谢谢.我感谢任何/所有反馈/见解.

Assumptions:

  1. 使用支持.on()//至少1.7版的jQuery
  2. 您希望将事件添加到动态添加的内容中

Readings/Examples:

  1. http://24ways.org/2011/your-jquery-now-with-less-suck
  2. http://brandonaaron.net/blog/2010/03/4/event-delegation-with-jquery
  3. http://www.jasonbuckboyer.com/playground/speed/speed.html
  4. http://api.jquery.com/on/

推荐答案

否-不应将所有委派的事件处理程序绑定到document对象.这可能是你能创造的最糟糕的情况.

首先,事件委托并不总是使您的代码更快.在某些情况下,这是有利的,而在某些情况下则不是.当您确实需要事件委派并且从中受益时,您应该使用事件委派.否则,您应该将事件处理程序直接绑定到发生事件的对象,因为这样通常效率更高.

其次,您不应该在文档级别绑定所有委托事件.这就是为什么.live()被弃用的原因,因为当你有很多事件以这种方式绑定时,这是非常低效的.对于委托事件处理,将它们绑定到最接近的非动态父级会更有效.

第三,并不是所有的活动都有效,或者所有的问题都可以通过授权来解决.例如,如果要截获输入控件上的键事件并阻止无效键进入输入控件,则不能通过委托事件处理来实现这一点,因为当事件冒泡到委托处理程序时,该事件已经由输入控件处理,现在影响该行为为时已晚.

以下是需要或有利的活动授权:

  • 当您在其上捕获事件的对象是动态创建/删除的,并且您仍然希望捕获它们上的事件,而不必在每次创建新的事件处理程序时显式地重新绑定事件处理程序.
  • 当您有许多对象都需要完全相同的事件处理程序时(其中数量至少为数百个).在这种情况下,在安装时绑定一个委托事件处理程序可能比绑定数百个或更多直接事件处理程序更有效.注意,委托事件处理在运行时的效率始终低于直接事件处理程序.
  • 当您试图(在文档中的更高级别)捕获文档中任何元素上发生的事件时.
  • 当您的设计明确使用事件冒泡和stopPropagation()来解决页面中的某些问题或功能时.

要进一步了解这一点,需要了解jQuery委托事件处理程序是如何工作的.当你这样称呼的时候:

$("#myParent").on('click', 'button.actionButton', myFn);

It installs a generic jQuery event handler on the #myParent object. When a click event bubbles up to this delegated event handler, jQuery has to go through the list of delegated event handlers attached to this object and see if the originating element for the event matches any of the selectors in the delegated event handlers.

由于 Select 器可能会相当复杂,这意味着jQuery必须解析每个 Select 器,然后将其与原始事件目标的特征进行比较,以查看它是否匹配每个 Select 器.这不是一个廉价的操作.如果只有一个 Select 器,这没什么大不了的,但是如果将所有 Select 器放在document对象上,并且有数百个 Select 器与每个冒泡事件进行比较,这可能会严重影响事件处理性能.

因此,您需要设置委托事件处理程序,以便委托事件处理程序尽可能接近目标对象.这意味着通过每个委托事件处理程序泡沫的事件更少,从而提高了性能.将所有委托事件放在Document对象上可能是最差的性能,因为所有冒泡事件都必须通过所有委托事件处理程序,并根据所有可能的委托事件 Select 器进行判断.这就是为什么.live()被弃用的原因,因为这就是.live()所做的,事实证明它的效率非常低.


So, to achieve optimized performance:

  1. 仅当委派事件处理实际上提供了您需要的功能或提高了性能时,才使用委派事件处理.不要总是使用它,因为它很容易,因为当你实际上不需要它的时候.它在事件分派时的性能实际上比直接事件绑定差.
  2. 将委派的事件处理程序尽可能附加到事件源最近的父级.如果您使用委托事件处理是因为您有要为其捕获事件的动态元素,那么请 Select 本身不是动态的最近父级.
  3. Use easy-to-evaluate selectors for delegated event handlers. If you followed how delegated event handling works, you will understand that a delegated event handler has to be compared to lots of objects lots of times so picking as efficient a selector as possible or adding simple classes to your objects so simpler selectors can be used will increase the performance of delegated event handling.

Jquery相关问答推荐

点击和touch 事件之间的jQuery冲突解决方法

如何在Jquery和Laravel中使用请求传递两个参数给Datatable

jQueryUI 模态对话框不显示关闭按钮 (x)

修改对象数组中的对象属性

如何使用 jQuery 重置 jquery Select 的 Select 选项?

一次替换多个字符串

如何在jQuery中 Select 具有特定ID的所有元素?

jQuery scrollTop 在 Chrome 中不工作但在 Firefox 中工作

如何在 Backbone.js - Backbone.sync 或 jQuery.ajax 中保存整个集合?

在单击事件上判断 Ctrl / Shift / Alt 键

如何使用jQuery动态设置宽度和高度

未捕获的 TypeError:data.push 不是函数

C# String.IsNullOrEmpty Javascript 等效项

当 iframe 在 jQuery 中完成加载时,如何触发事件?

如何使锚链接不可点击或禁用?

AngularJS:使用 jQuery 更改时,ng-model 绑定不更新

jQuery attr 与props ?

如何使用 jquery 更改元素类型

获取对象属性中的最小值/最大值的快速方法

在 JavaScript 开头使用分号的目的是什么?