2012-03-14 47 views
17

在本网站现在大多数人可能知道:为什么不把Javascript事件委托给极端?

$("#someTable TD.foo").click(function(){ 
    $(e.target).doSomething(); 
}); 

想要进行更糟糕的比:

$("#someTable").click(function(){ 
    if (!$(e.target).is("TD.foo")) return; 
    $(e.target).doSomething(); 
}); 

现在如何,当然差很多将取决于你有多少次达阵表有,但是这个一般原则应该适用,只要你至少有几个TD。 (注意:当然,聪明的事情是使用jQuery代表而不是上面的代码,但我只是想用一个明显的区别来做一个例子)。

无论如何,我向同事解释了这个原则,他们的回答是:“对于站点范围的组件(例如,日期选择INPUT),为什么要停下来呢?为什么不为每种类型绑定一个处理程序的组件给BODY本身?“我没有一个好的答案。

很明显,使用委托策略意味着重新思考如何阻止事件,所以这是一个缺点。此外,假设您可能有一个页面,您有一个“TD.foo”,不应该有一个事件挂钩它。但是,如果你了解并愿意解决事件冒泡的变化,并且如果你强制执行“如果你在TD上放置.foo,它总会让事件挂钩”的策略,这两者似乎都不是大不了。

我觉得我必须错过一些东西,所以我的问题是:是否有任何其他缺点只是将所有站点范围组件的所有事件委托给BODY(而不是将它们直接绑定到涉及的HTML元素,或将它们委托给非BODY父元素)?

+0

我相信这是偏好的问题和案件逐案情况。我的意思是,你应该首先编写代码以尽可能可读。这样,您或其他人就可以在后面进入并检查代码,并且可以轻松使用它。完成之后,您可以检查代码是否运行良好,并根据需要进行优化。在你的特定场景中,$(“someTable TD.foo”)比返回它的场景更容易阅读,管理和关注。有人可能会读取其他代码并对其进行曲解,导致他们在更改时引入错误。只是我的意见 – evasilchenko 2012-03-14 22:27:17

+0

我完全同意:开发人员应该先设计,而不必担心优化问题,只能在适当的时候进行优化。然而,这整个事情是出于现实需要,以优化现有设计(我们有一个伟大的页面,直到我们的客户决定使用它成千上万的行),所以我们试图提出最好的策略来处理这种优化。 – machineghost 2012-03-15 21:21:26

+1

可能重复的[应该所有的jQuery事件绑定到$(文档)?](http://stackoverflow.com/q/12824549/1048572) – Bergi 2014-12-11 02:03:48

回答

20

你缺少的是性能的不同元素。

您的第一个示例在设置点击处理程序时性能会更差,但在触发实际事件时效果会更好。

第二个示例在设置点击处理程序时性能更好,但在实际事件触发时性能明显变差。

如果所有事件都放在顶层对象(如文档)上,那么您将拥有大量选择器来检查每个事件,以便查找它所处理的处理函数。这就是为什么jQuery弃用.live()方法的原因,因为它查找文档对象上的所有事件,并且当有很多注册的事件处理程序时,每个事件的执行都很糟糕,因为它必须将每个事件与众多选择器进行比较为该事件找到适当的事件处理程序。对于大规模工作,将事件绑定到触发事件的实际对象附近要高效得多。如果对象不是动态的,则将事件绑定到将触发它的对象。当您第一次绑定事件时,这可能会花费更多的CPU,但实际的事件触发将会很快并且会缩放。

jQuery的.on().delegate()可用于此目的,但建议您找到一个尽可能接近触发对象的祖先对象。这可以防止在一个顶级对象上累积大量动态事件,并防止事件处理的性能下降。

在你上面的例子,这是完全合理的事情:

$("#someTable").on('click', "td.foo", function(e) { 
    $(e.target).doSomething(); 
}); 

这将使你的所有行的点击处理程序的一个紧凑表示,它将继续工作,即使你添加/删除行。

但是,这不会使多大意义:

$(document).on('click', "#someTable td.foo", function(e) { 
    $(e.target).doSomething(); 
}); 

,因为这将是混合表事件在页面中所有其他顶级赛事时,有没有真正需要做到这一点。您只是在事件处理中要求性能问题,而没有处理那些事件的任何好处。

所以,我认为你的问题的简短答案是,处理所有事件在一个顶级的地方导致性能问题,当事件被触发,因为代码必须清理哪个处理程序应该得到的事件,当有很多事件在同一个地方处理。尽可能接近生成对象处理事件使事件处理更加高效。

+1

谢谢你的详细解释。在我们查看的情况(包含数万个TD的表格)中,事件连接性能是瓶颈,但您的解释帮助我了解,在我们网站的许多其他相关案例中,事件解决性能将比事件更重要连接性能(对文档过多的绑定会对分辨率性能产生负面影响)。所以......我们现在不会全局约束一切:-) – machineghost 2012-03-15 00:02:36

3

如果你是用普通的JavaScript做的话,页面上随机点击触发事件的影响几乎为零。然而,在jQuery中,由于必须运行以产生相同效果的原始JS命令的数量,后果可能会更大。

就我个人而言,我发现有一点委托是好的,但太多的问题会导致更多的问题而不是解决问题。

3
  • 如果删除节点,则相应的侦听器不会自动删除。
  • 有些事件只是不冒泡
  • 不同的库可通过停止事件传播破坏系统(猜你提到一个)