javascript - 为什么不将 Javascript 事件委托(delegate)发挥到极致呢?

标签 javascript javascript-events

到目前为止,该网站上的大多数人可能都知道:

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

将表现得比:
$("#someTable").click(function(){
    if (!$(e.target).is("TD.foo")) return;
    $(e.target).doSomething();
});

现在,更糟的程度当然取决于您的 table 有多少 TD,但只要您至少有几个 TD,这个一般原则就应该适用。 (注意:当然,聪明的做法是使用 jQuery 委托(delegate)而不是上面的,但我只是想举一个明显不同的例子)。

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

显然,使用委托(delegate)策略意味着重新考虑如何阻止事件,所以这是一个缺点。此外,假设您可能有一个页面,其中您有一个“TD.foo”,它不应该有一个事件连接到它。但是,如果您了解并愿意解决事件冒泡更改,并且如果您执行“如果您将 .foo 放在 TD 上,它总是会连接事件”的政策,那么这些似乎都不像大不了。

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

最佳答案

你缺少的是表演的不同元素。

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

您的第二个示例在设置单击处理程序时表现更好,但在触发实际事件时表现明显更差。

如果所有事件都放在顶级对象(如文档)上,那么您将有一个巨大的选择器列表来检查每个事件,以便找到它与哪个处理函数一起使用。这个问题就是 jQuery 弃用 .live() 的原因。方法,因为它会查找文档对象上的所有事件以及何时有很多 .live()注册了事件处理程序后,每个事件的性能都很差,因为它必须将每个事件与大量选择器进行比较,才能为该事件找到合适的事件处理程序。对于大规模工作,将事件绑定(bind)到接近触发事件的实际对象会更有效。如果对象不是动态的,则将事件权限绑定(bind)到将触发它的对象。当您第一次绑定(bind)事件时,这可能会花费更多的 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();
});

因为当没有真正需要这样做时,这会将表格事件与页面中的所有其他顶级事件混合在一起。您只要求事件处理中的性能问题,而没有处理那里的事件的任何好处。

因此,我认为对您的问题的简短回答是,在触发事件时在一个顶级位置处理所有事件会导致性能问题,因为当有很多事件发生时,代码必须理清哪个处理程序应该获取事件在同一个地方处理。处理尽可能接近生成对象的事件使事件处理更有效。

关于javascript - 为什么不将 Javascript 事件委托(delegate)发挥到极致呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9711118/

相关文章:

javascript - this.parentElement 是什么?

javascript - 我可以在 beforeUnload 中放什么?

javascript-events - 通过javascript将下拉onchange函数中的所选项目显示到html标签中,请帮助如何操作

javascript - jQuery 模板插件和数据持久性

javascript - 如何使用 FormData 将文件发送到 Nodejs 并让 Node 发回确认消息?

javascript - 如何为pg Node js插入未定义的值作为null

javascript - 如何检测服务器是否关闭?

javascript - 是否有一个普通函数可以在不影响后代节点的情况下删除所有事件监听器?

javascript 打印操作 - 打印日期/url

javascript - 试图获取等于按钮以在计算器中正常运行