Javascript 在主体或单个元素组上存储单击事件是否更有效

Javascript 在主体或单个元素组上存储单击事件是否更有效,javascript,Javascript,我读到以下内容: “如果用户可以与页面上的许多元素交互,则向每个元素添加事件侦听器会占用大量内存并降低性能 …因为事件影响包含元素,所以您可以将事件处理程序放置在包含元素上,并使用事件目标属性找出事件发生在其哪个子元素上“ 那么,在身体上只做一次点击事件,然后授权正确的功能有什么坏处呢 我举了一个例子: 死链接的代码备份: HTML: 有趣的一点是:每次用户单击时,它都会引发一个事件。但是,这真的会成为一个问题吗?它所做的只是通过一个开关进行检查(如果检查,也可能是) 这一点仅仅是兴趣,然而用户

我读到以下内容:

“如果用户可以与页面上的许多元素交互,则向每个元素添加事件侦听器会占用大量内存并降低性能

…因为事件影响包含元素,所以您可以将事件处理程序放置在包含元素上,并使用事件目标属性找出事件发生在其哪个子元素上“

那么,在身体上只做一次点击事件,然后授权正确的功能有什么坏处呢

我举了一个例子:

死链接的代码备份:

HTML:

有趣的一点是:每次用户单击时,它都会引发一个事件。但是,这真的会成为一个问题吗?它所做的只是通过一个开关进行检查(如果检查,也可能是)


这一点仅仅是兴趣,然而用户询问了点优化。我认为这可能会很快得到进一步优化,但我会继续讨论这个话题。

与大多数这类事情一样,答案是“视情况而定”,你需要选择一个中间立场。一般来说,建议在DOM树中至少将事件放置在与其源相对较近的位置,以避免过度冒泡,并避免将事件放置在
主体上,除非有必要

例如,您可以在
ul
上放置一个处理程序来处理
li
s的事件委派:

document.getElementById('test4').addEventListener('click', function (e) {
    // handle event for li
});
这将为您提供两全其美的体验,因为您:

  • 将一个事件绑定到DOM以处理
    li
    单击,而不是为每个
    li
  • 如果动态修改
    li
    s的集合,则不必重新附加事件
  • 气泡最小(仅一级)
  • 不必在一个丑陋的开关语句中多路传输逻辑

因此,我认为这是一个值得牢记的原则。

如果您将所有内容都放在正文上,那么您在页面上的任何单击都需要经过它。性能上的影响在移动设备上更为明显。有了这么多的元素,我甚至不担心它。除非您分析了代码并发现这是一个瓶颈,否则这是过早的优化。如果有几个元素在单击时都需要执行相同(或几乎相同)的操作,那么在更高级别附加处理程序是有意义的。否则,我认为
switch
语句将是一场噩梦。是的,这是一次演示。我认为黄教提出了一个很好的观点,谢谢你,正是@Huangism所说的,所以通常你应该试着找到一些“中间立场”。页面上可能有更多的元素需要(公共)单击处理程序,但如果这些元素按容器元素分组,则可以将处理程序放置在该元素上,而不是“一直”到正文…特别是如果有许多其他元素根本不需要处理它们的单击(或通过不同的处理程序函数)@user2330270:如果你已经对其进行了分析,那么你想问什么?看看哪一个更有效。1.事件绑定到主体,因此它只会冒泡到HTML级别。如果你在每个元素上进行了分析,它仍然会冒泡向上,因此初学者需要更加小心2.你可以优化切换到ul的唯一帐户,这是一个快速的解决方案演示3.见#14.好吧,Maaaybe,你明白我的意思了;)但我要说明我的观点,一个开关比一堆事件代码更清晰还是更模糊?5.请参阅,以通过类选择6指定要附加事件的节点。谢谢你的回复,非常感谢appreciated@user2330270我的第一点与冒泡无关。关于冒泡,你的理解是冒泡是倒退的。如果有人在DOM的深处单击某个元素,则该事件必须从父级向上移动,直到得到处理。这就是冒泡的性能问题。@user2330270您不必相信我关于冒泡的问题。查看关于事件冒泡性能的说明:“为了获得最佳性能,请将委派事件附加到尽可能靠近目标元素的文档位置。避免在大型文档上过度使用document或document.body作为委派事件。”事实上,几乎没有人使用一个事件处理程序来处理一个页面上的所有事件,所以这应该是一个很好的提示,这可能不是最好的方法。啊,很有趣。这似乎与我的书相矛盾,正是我的书导致了这一点。它说,如果您在头和子元素上绑定了事件,那么当您单击子元素时,它将触发绑定到任何/所有父节点的任何单击事件。从您所说的内容来看,它被吸收了?@user2330270子级上的事件处理程序将能够停止传播(使用
e.stopPropagation()
)并防止事件进一步冒泡。
var body = document.body;

if (body.addEventListener) {
    body.addEventListener('click', function (e) {
        delegate(e, "click");
    }, false);
} else {
    body.attachEvent('onclick', function (e) {
        delegate(e, "click");
    }, false);
}


function delegate(e) {
    var sourceNode = e.target || e.srcElement;
    var id = sourceNode.id;
    switch (id) {
        case ("test"):
            // do some func
            break;
        case ("test2"):
            // do some func
            break;
        case ("test3"):
            // do some func
            break;
        case ("test4"):
            // do some func
            break;
        default:
            // do nothing
            break;

    }
}
document.getElementById('test4').addEventListener('click', function (e) {
    // handle event for li
});