当前位置: 首页 > 面试题库 >

是否所有jquery事件都应绑定到$(document)?

祖浩淼
2023-03-14
问题内容

这是哪里来的

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

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

在学习了更多关于选择器速度和事件委托的知识之后,我在几个地方读到“ 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);

我要实现的目标:

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

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

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

这似乎可以满足我的所有目标。(是的,由于某种原因,它在IE中的运行速度较慢,不知道为什么吗?)之所以快,是因为只有单个事件绑定到单个元素,并且仅在事件发生时才评估辅助选择器(如果此处有误,请更正我)。命名空间很棒,因为它使切换事件侦听器更加容易。

我的解决方案/问题

因此,我开始认为jQuery事件应始终绑定到$(document)。
有什么理由为什么您不想这样做?
可以认为这是最佳做法吗?如果没有,为什么?

如果您已经阅读了整本书,那么谢谢。我感谢任何/所有反馈/见解。

假设:

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

问题答案:

否-不应将所有委托的事件处理程序绑定到该document对象。这可能是您可能创建的性能最差的方案。

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

其次,您不应在文档级别绑定所有委托事件。这正是.live()被弃用的原因,因为当您以这种方式绑定许多事件时,效率非常低。对于委托事件处理,将它们绑定到非动态的最接近的父级要高效得多。

第三,不是所有事件都能奏效或所有问题都可以通过委托解决。例如,如果要拦截输入控件上的键事件并阻止将无效键输入到输入控件中,则不能使用委托事件处理来执行此操作,因为到事件冒泡到委托处理程序时,它已经已由输入控件处理,现在来影响该行为为时已晚。

在某些情况下,需要进行事件委派或有利于进行事件委派:

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

为了进一步了解这一点,需要了解jQuery委托事件处理程序的工作方式。当您调用类似这样的内容时:

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

它将在#myParent对象上安装通用jQuery事件处理程序。当click事件冒泡到此委托事件处理程序时,jQuery必须遍历附加到此对象的委托事件处理程序列表,并查看事件的原始元素是否与委托事件处理程序中的任何选择器匹配。

因为选择器可以相当广泛地参与其中,所以这意味着jQuery必须解析每个选择器,然后将其与原始事件目标的特征进行比较,以查看它是否与每个选择器匹配。这不是一个便宜的操作。如果只有一个选择器,这没什么大不了的,但是如果将所有选择器放在文档对象上,并且有数百个选择器要与每个冒泡事件进行比较,这会严重影响事件处理性能。

因此,您需要设置委托事件处理程序,以使委托事件处理程序尽可能接近目标对象。这意味着更少的事件将在每个委派的事件处理程序中冒泡,从而提高了性能。将所有委托事件放在文档对象上是最糟糕的性能,因为所有冒泡事件都必须经过所有委托事件处理程序并针对所有可能的委托事件选择器进行评估。这就是为什么.live()不赞成这样.live()做的原因,因为这样做是事实,并且事实证明效率很低。

因此,要实现优化的性能:

  1. 仅在实际提供所需功能或提高性能时才使用委托事件处理。不要总是使用它,因为它很容易,因为当您实际上不需要它时。实际上,它在事件分发时的性能要比直接事件绑定差。
  2. 尽可能将委派的事件处理程序附加到与事件源最近的父级。如果使用委派事件处理是因为您具有要为其捕获事件的动态元素,请选择本身不是动态的最接近的父级。
  3. 对委托的事件处理程序使用易于评估的选择器。如果您遵循委托事件处理的工作原理,您将了解必须多次将委托事件处理程序与许多对象进行比较,因此,选择效率尽可能高的选择器或向对象添加简单的类,以便可以使用更简单的选择器提高委托事件处理的性能。


 类似资料:
  • 问题内容: 是否可以使用jQuery确定元素是否具有单击处理程序,更改处理程序或绑定到其的任何类型的事件处理程序? 此外,是否可以确定给定类型的事件有多少个单击处理程序(或任何类型的事件处理程序),以及事件处理程序中包含哪些功能? 问题答案: 您可以从数据缓存中获取此信息。 例如,将它们记录到控制台(firebug,即ie8): 或迭代它们:

  • 问题内容: 如何使用jQuery将函数绑定到HTML5 localStorage更改事件? 我已经尝试了上述方法,但没有显示警报。 更新 :它可以在Firefox 3.6中运行,但不能在Chrome8或IE8中运行,因此问题应该更多是“如何在所有浏览器上使用jQuery绑定到localStorage更改事件?” 问题答案: 事实证明,这实际上是正确的,并且我误解了规范 当在与本地存储区域相关联的存

  • 我正在尝试创建一个3个月向前看类型表。因此,例如,任何(即Jan-2021)的事件在2021年2月和2021年3月也是有效的。 对于每一个事件,我想在发生后的2个月内再排一次。以下示例: 给定如下所示的数据: 我想创建一些看起来像这样的东西: 有点纠结于如何实现这一点。您可以假设在这里是有效的datetime字段。我试过几种不同的方法都没有用。对于类似的情况,我通常使用窗口函数,这里有和限制,但和

  • 本文向大家介绍浅谈jquery之on()绑定事件和off()解除绑定事件,包括了浅谈jquery之on()绑定事件和off()解除绑定事件的使用技巧和注意事项,需要的朋友参考一下 off()函数用于移除元素上绑定的一个或多个事件的事件处理函数。 off()函数主要用于解除由on()函数绑定的事件处理函数。 该函数属于jQuery对象(实例)。 语法 jQuery 1.7 新增该函数。其主要有以下两

  • 问题内容: 我凭经验发现 绑定到当前计算机上的所有网络接口(而不仅仅是localhost-127.0.0.1或主机名),但是我无法找到说明这是可以保证的文档。 问题:在Java中绑定到0.0.0.0的定义将始终绑定到所有网络接口? 问题答案: 使用将仅绑定到启用IPv4的接口。但是,如果绑定到,则假定您的TCP / IP堆栈(和Java)启用了IPv4兼容的IPv6套接字,则该协议应涵盖所有IPv

  • 本文向大家介绍浅谈jQuery事件绑定原理,包括了浅谈jQuery事件绑定原理的使用技巧和注意事项,需要的朋友参考一下 jq里面有一个data的方法,给dom元素绑定相关的数据的。当给dom用jq的方法绑定了事件,会生成对应的时间列表 可以看下面的例子(请在firefox中查看 因为firefox中对象支持toSource())   data是给元素绑定数据的 数据源是 cache对象 当元素绑定