为什么不把JavaScript事件委托给极端?
到目前为止,大多数人都知道:
$("#someTable TD.foo").click(function(){ $(e.target).doSomething(); });
会比下面的performance要差得多:
$("#someTable").click(function(){ if (!$(e.target).is("TD.foo")) return; $(e.target).doSomething(); });
现在要差多less,当然要取决于你的表有多less个TD,但是这个总体原则应该适用,只要你至less有几个TD。 (注意:当然,聪明的事情是使用jQuery代表,而不是上面的,但我只是试图做一个明显的区分例子)。
无论如何,我向同事解释了这个原则,他们的回答是:“对于站点范围的组件(例如,dateselectINPUT),为什么要停下来呢?为什么不把每个types的组件的一个处理程序绑定到BODY本身?“ 我没有一个好的答案。
显然,使用委托策略意味着重新思考如何阻止事件,所以这是一个缺点。 另外,假设你有一个页面,你有一个“TD.foo”, 不应该有一个事件挂钩。 但是,如果你明白并且愿意为事件冒泡改变而工作,并且如果你强制执行一个“如果你把TD放在.foo上,总会把事件挂钩”的策略,这些都不是大不了。
我觉得我必须错过一些东西,所以我的问题是:是否有任何其他的缺点,只是将所有站点范围组件的所有事件委托给BODY(而不是直接绑定到HTML元素,或委托他们到一个非BODY父元素)?
你缺less的是性能的不同元素。
您的第一个示例在设置点击处理程序时性能较差,但在实际事件触发时性能会更好。
你的第二个例子在设置点击处理器的时候performance更好,但是当实际的事件被触发的时候performance会更差。
如果所有的事件都放在顶层的对象上(比如文档),那么你将有一个巨大的select器列表来检查每一个事件,以便find它所处理的处理函数。 这就是为什么jQuery不赞成使用.live()
方法,因为它查找文档对象上的所有事件,以及注册了.live()
事件处理程序时,每个事件的执行都很糟糕,因为它必须比较每个事件到很多很多的select器来find适当的事件处理程序。 对于大规模的工作来说,将事件绑定到触发事件的实际对象更为有效。 如果对象不是dynamic的,则将事件绑定到将触发它的对象。 当您第一次绑定事件时,这可能会花费更多的CPU,但是实际的事件触发将会很快并且会缩放。
jQuery的.on()
和.delegate()
可以用于这个,但是build议你find一个尽可能接近触发对象的祖先对象。 这可以防止在一个顶级对象上形成大量dynamic事件,并防止事件处理的性能下降。
在你上面的例子中,这是完全合理的:
$("#someTable").on('click', "td.foo", function(e) { $(e.target).doSomething(); });
这将给你一个紧凑的表示所有行的点击处理程序,它会继续工作,即使你添加/删除行。
但是,这不会有多less意义:
$(document).on('click', "#someTable td.foo", function(e) { $(e.target).doSomething(); });
因为如果没有真正需要的话,这将会把表格事件与页面中的所有其他顶级事件混合在一起。 您只是在事件处理中要求性能问题,没有任何处理事件的好处。
所以,我认为你的问题的简短答案是,处理所有事件在一个顶级的地方导致性能问题,当事件被触发,因为代码必须清理哪个处理程序应该得到事件,当有很多事件在同一个地方处理。 尽可能接近生成对象处理事件使事件处理更加高效。
如果你用普通的JavaScript做的话,页面上随机点击触发事件的影响几乎为零。 然而,在jQuery中,由于需要运行的原始JS命令的数量会产生相同的效果,所以后果可能会更大。
就我个人而言,我发现一个小小的代表团是好的,但是太多的代表团会开始造成比解决问题更多的问题。
- 如果删除节点,则相应的侦听器不会自动删除。
- 有些事件只是不泡
- 不同的图书馆可能会通过停止事件传播来破坏系统(猜你提到过那个)
- Angular / UI路由器 – 如何更新url而不刷新所有内容?
- 在提供JavaScript文件时,使用应用程序/ javascript还是application / x-javascript会更好
- HTML5 / Canvas支持双caching吗?
- Chrome浏览器JavaScript开发者控制台:是否可以在不使用换行符的情况下调用console.log()?
- 抑制JSHint / JSLint或替代服务中的“混合空格和制表符”警告?
- 将PHPvariables传递给Javascript的最佳方式是什么?
- jQuery循环通过具有相同类的元素
- Angularjs不会在ng-view中加载脚本
- “在AngularJS中思考”如果我有一个jQuery背景?