问题:我需要在动态运行时将任意数量的事件处理程序绑定到任意数量的元素(DOM节点window
,document
),我需要能够在页面生命周期内更新动态创建(或销毁)节点的事件绑定。我可以看到有三种方法可以解决这个问题:
I)window
上的事件代表团
II)每个节点上的直接事件绑定
III)共同祖先的事件委托(直到运行时才会知道,并且在DOM被更改时可能需要重新计算)
最有效的方法是什么?
我正在处理一组需要对用户事件进行分析跟踪(点击,滚动等)的页面,我希望能够在一堆页面上轻松配置这些事件处理程序,而无需编写脚本处理每个实例的事件绑定。此外,因为我可能需要在将来跟踪新事件,或者跟踪动态添加到页面/从页面中删除的元素上的事件,我需要能够考虑在生命周期中发生的DOM中的更改页面。
作为我目前正在考虑的一个例子,我想创建一个接受配置对象的函数,该对象允许程序员为每个事件指定默认处理程序,并允许它们为特定元素覆盖它们:
Analytics.init({
// default handlers for each event type
defaultHandlers: {
"click": function(e) { ... },
"focus": function(e) { ... }
},
// elements to listen to
targetElements: {
// it should work with non-DOM nodes like 'window' and 'document'
window: {
// events for which the default handlers should be called
useDefaultHandlers: ['click'],
// custom handler
"scroll": function(e) { ... }
},
// it should work with CSS selectors
"#someId": {
useDefaultHandlers: ['click', 'focus'],
"blur": function(e) { ... }
}
}
});
答案 0 :(得分:1)
我通常会在document.documentElement
对象上委托事件,因为:
<html>
元素,至于事件委托的效率,事件必须冒出的节点越多,所需的时间越长,但是我们正在谈论~1到2毫秒的时差 - 可能。这对用户来说是不可察觉的。通常是处理DOM事件会导致性能损失,而不是事件从一个节点冒泡到另一个节点。
我发现以下事情通常会对JavaScript性能产生负面影响:
主要是,#1影响最大。我认为在大多数情况下,试图在事件处理中提高性能是一种过早的优化。我看到优化事件处理代码的唯一情况是当你有一个每秒触发多次的事件时(例如“scroll”和“mousemove”事件)。事件委派的附加好处是,您不必清理将与文档树分离的DOM节点上的事件处理程序,从而允许浏览器对该内存进行垃圾收集。
(来自下面的评论)wvandell说:
事件委派的性能成本与事件的实际“冒泡”几乎没有关系......将许多选择器委派给单个父级时会产生性能损失。
这是事实,但让我们考虑一下感知的表现。委派许多点击事件对用户来说是不明显的。如果您委派了scroll
或mousemove
这样的事件,每秒可以发送超过50次(剩余20毫秒来处理事件),那么用户就可以感知到性能问题。这又回到了我反对过早优化事件处理程序代码的论点。
可以在共同祖先(例如document.documentElement
)上委派许多点击事件而没有任何问题。我会在那里委托“mousemove”活动吗? 可能。这取决于发生了什么,以及委托“mousemove”事件是否足够响应。