Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/472.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript理解事件委托的需要_Javascript - Fatal编程技术网

JavaScript理解事件委托的需要

JavaScript理解事件委托的需要,javascript,Javascript,我在网上的一篇文章中读到这句话: 将事件处理程序添加到1000个单元格中的每个单元格将是一个主要问题 性能问题,可能是浏览器崩溃的根源 内存泄漏 但我不明白。例如,如果我正在做这样的事情: const handler = e => // do something document.querySelectorAll("td").forEach(td => { td.addEventListener("click", handler); }); 我不创建1000个函数,它们都使

我在网上的一篇文章中读到这句话:

将事件处理程序添加到1000个单元格中的每个单元格将是一个主要问题 性能问题,可能是浏览器崩溃的根源 内存泄漏

但我不明白。例如,如果我正在做这样的事情:

const handler = e => // do something

document.querySelectorAll("td").forEach(td => {
   td.addEventListener("click", handler);
});

我不创建1000个函数,它们都使用相同的引用,所以我缺少什么?问题出在哪里?

在JavaScript中,事件会在DOM链中冒泡。当您单击
td
时,
td
上的任何事件处理程序都将启动,
tr
上的
表上的
等都将启动

本文告诉您在
(例如)上注册事件,而不是在每个
td
元素上注册事件

我没有创建1000个函数,它们都使用相同的引用,所以 我错过了什么?有什么问题

您不是在创建1000个函数,而是在注册1000个事件处理程序,这正是本文所建议的。而是在某个父元素上注册一个事件处理程序,如
table


下面介绍如何为1000个表单元格注册一个事件处理程序。

事件委派的工作方式是在父元素中添加一个事件侦听器。当父级触发事件时,您将获得触发事件的实际元素的引用,然后检查该元素是否是您要侦听的元素 也许一个代码可以帮助你更好地理解它

// Listen for the event on the parent...
document.getElementById("event-table").addEventListener("click", function(e) {
    // '.target' will now give us our actual clicked element
    if(e.target && e.target.nodeName == "td") {
        // Wooho, a '<td>' node was clicked
        console.log("We have our click event delegated!");
    }
});
//侦听父节点上的事件。。。
document.getElementById(“事件表”).addEventListener(“单击”,函数(e){
//“.target”现在将为我们提供实际单击的元素
if(e.target&&e.target.nodeName==“td”){
//Wooho,已单击“”节点
log(“我们委托了我们的点击事件!”);
}
});
它的帮助方式是,现在,我不需要在每个元素上添加eventListner,只需将它附加到父元素,然后检查它的子元素

此功能的真正用途是当您希望在某些动态创建的元素上附加事件时。假设表中的一行是在数据库调用后动态添加的。在这种情况下,如果要将事件附加到每个节点,则必须将事件侦听器重新附加到新节点。但是,如果使用委派方法,由于事件附加到父节点,新创建的子节点将自动成为事件的一部分

如果将其附加到具有多个子节点的父节点,而这些子节点实际上不是事件的预期节点,则可能会降低性能。例如,如果您附加主体节点本身,然后将其委托给其中的“td”标记!从理论上讲,它肯定会起作用,但可能会减慢速度

我没有创建1000个函数,它们都使用相同的引用,那么我缺少什么呢


您仍然可以在1000个DOM节点中创建1000个函数引用。这似乎并不重要,但表可能会增长


当然,您基本上是对的,如果您不创建1000个闭包,就不会有那么多问题。然而,你真的有1000个按钮都做同样的事情吗?使用闭包,很容易让它们做一些稍微不同的事情;如果只使用一个函数,则需要使其动态依赖于单击的单元格(事件目标)。当您已经在这样做的时候,您可以只使用一个函数引用和事件委托…

也许一个类比可以帮助您更好地理解它。假设你有一家公司,客户打电话给你,你给他们寄了一些东西

  • 将一个独特的事件处理程序附加到每个手机上需要1000条电话线,每个客户一条,并且必须雇佣1000名员工来管理每个等待订单的手机
  • 将一个事件处理程序连接到所有手机就像仍然有1000条电话线,每个客户一条,但由一名员工监控,该员工必须找出哪个客户的电话线正在响,以及在哪里发送信息。您不再需要1000名员工,但仍有1000条电话线
  • 使用事件委派就像拥有一条所有客户都可以拨打的电话线和一名员工,他们知道根据来电者id将他们的东西发送到哪里

使用一条电话线可以让您的员工更加高效。

如果我理解的话,您担心内存泄漏。我们的想法是,每次单击一个
td
时,每次单击都会执行该处理程序,因为您需要绑定1000个事件,这不是免费的。(在你的例子中,你绑定了一个事件)请链接你正在阅读的文章,引用引文,我们得到一些上下文。你没有回答我的问题。请再读一遍。您没有向OP解释为什么绑定1000个事件不好。您解释了冒泡。@未定义,我已将我的答案更明确。我还添加了一个JSFIDLE示例,演示如何仅在一个父元素上添加事件侦听器。正如@epascarello所说,您没有向OP解释为什么绑定1000个事件不好。你解释了冒泡。@未定义,希望能回答你的问题question@MayankRaj关于动态创建的元素,这一点很好+1“您仍将创建1000个函数引用”,请您进一步解释一下好吗?据我所知,所有的参考点都是您有一个引用。如果您将同一个事件处理程序添加到1000个单元格中,则每个单元格都有自己对处理程序函数的引用。考虑使用
.onclick
绑定事件,这将创建1000个属性。