我想对 jfriend00 的回答添加一些评论和反驳。(主要是基于我的直觉我的意见)
不 - 您不应该将所有委托的事件处理程序绑定到文档对象。这可能是您可以创建的性能最差的场景。
首先,事件委托并不总是让你的代码更快。在某些情况下,这是有利的,在某些情况下则不是。当您真正需要事件委托并从中受益时,您应该使用事件委托。否则,您应该将事件处理程序直接绑定到事件发生的对象,因为这通常会更有效。
虽然如果您只为单个元素注册和事件,性能可能会稍好一些,但我相信它不会与委托带来的可扩展性优势相提并论。我也相信浏览器正在(将会)越来越有效地处理这个问题,尽管我没有证据证明这一点。在我看来,事件委托是要走的路!
其次,您不应该在文档级别绑定所有委托事件。这正是 .live() 被弃用的原因,因为当您有很多以这种方式绑定的事件时,这非常低效。对于委托事件处理,将它们绑定到最近的非动态父级会更有效。
我有点同意这一点。如果您 100% 确定事件只会发生在容器内,那么将事件绑定到该容器是有意义的,但我仍然反对将事件直接绑定到触发元素。
第三,并非所有事件都有效或所有问题都可以通过委派来解决。例如,如果您想拦截输入控件上的键事件并阻止将无效键输入到输入控件中,则不能使用委托事件处理来执行此操作,因为当事件冒泡到委托处理程序时,它已经已由输入控件处理,现在影响该行为为时已晚。
这是不正确的。请看这个codePen:https ://codepen.io/pwkip/pen/jObGmjq
document.addEventListener('keypress', (e) => {
e.preventDefault();
});
它说明了如何通过在文档上注册 keypress 事件来防止用户键入。
以下是需要或有利的事件委托的时候:
当您捕获事件的对象是动态创建/删除时,您仍然希望在它们上捕获事件,而不必在每次创建新事件处理程序时显式重新绑定事件处理程序。当您有很多对象都需要完全相同的事件处理程序时(其中很多对象至少有数百个)。在这种情况下,在设置时绑定一个委托事件处理程序可能比绑定数百或更多直接事件处理程序更有效。请注意,委托事件处理在运行时的效率总是低于直接事件处理程序。
我想回复来自https://ehsangazar.com/optimizing-javascript-event-listeners-for-performance-e28406ad406c的这句话
Event delegation promotes binding as few DOM event handlers as possible, since each event handler requires memory. For example, let’s say that we have an HTML unordered list we want to bind event handlers to. Instead of binding a click event handler for each list item (which may be hundreds for all we know), we bind one click handler to the parent unordered list itself.
此外,谷歌搜索performance cost of event delegation google
返回更多有利于事件委托的结果。
当您尝试捕获(在文档中的更高级别)发生在文档中任何元素上的事件时。当您的设计明确使用事件冒泡和 stopPropagation() 来解决页面中的某些问题或功能时。要进一步理解这一点,需要了解 jQuery 委托事件处理程序是如何工作的。当你调用这样的东西时:
$("#myParent").on('click', 'button.actionButton', myFn); 它在#myParent 对象上安装了一个通用的jQuery 事件处理程序。当点击事件冒泡到该委托事件处理程序时,jQuery 必须遍历附加到该对象的委托事件处理程序列表,并查看事件的原始元素是否与委托事件处理程序中的任何选择器匹配。
因为选择器可以相当多地涉及,这意味着 jQuery 必须解析每个选择器,然后将其与原始事件目标的特征进行比较,以查看它是否与每个选择器匹配。这不是一个便宜的操作。如果只有其中一个也没什么大不了的,但是如果您将所有选择器放在文档对象上,并且有数百个选择器要与每个冒泡事件进行比较,这可能会严重影响事件处理性能。
出于这个原因,您希望设置您的委托事件处理程序,以便委托事件处理程序尽可能接近目标对象。这意味着更少的事件将通过每个委托的事件处理程序冒泡,从而提高性能。将所有委托事件放在文档对象上是最差的性能,因为所有冒泡事件都必须通过所有委托事件处理程序并针对所有可能的委托事件选择器进行评估。这正是 .live() 被弃用的原因,因为这是 .live() 所做的,并且被证明是非常低效的。
这是在哪里记录的?如果这是真的,那么 jQuery 似乎以一种非常低效的方式处理委托,然后我的反驳论点应该只适用于 vanilla JS。
仍然:我想找到支持这一说法的官方消息来源。
:: 编辑 ::
似乎 jQuery 确实以非常低效的方式进行事件冒泡(因为它们支持 IE8)
https://api.jquery.com/on/#event-performance
所以我在这里的大部分论点只适用于 vanilla JS 和现代浏览器。