动态绑定事件处理程序的最有效方法
Most efficient way to dynamically bind event handlers
问题:我需要在动态运行时将任意数量的事件处理程序绑定到任意数量的元素(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) { ... }
}
}
});
来源
- SO:所有jQuery事件都应该绑定到文档吗
- SO:如何找到两个或多个节点的最近共同祖先
- jQuery文档:$.fn.on()
我通常委托document.documentElement
对象上的事件,因为:
- 它表示页面上的
<html>
元素,其中包含所有内容包含用户可以交互的所有HTML标记 - 它可在JavaScript开始执行时使用,不需要窗口加载或DOM就绪事件处理程序
- 您仍然可以捕获"滚动"事件
至于事件委派的效率,事件必须出现的节点越多,所需时间就越长,但我们谈论的是大约1到2毫秒的时间差——可能。用户无法察觉。通常是对DOM事件的处理会带来性能损失,而不是将事件从一个节点冒泡到另一个节点。
我发现以下因素通常会对JavaScript性能产生负面影响:
- 文档树中的节点越多,浏览器操作它就越耗时
- 页面上的事件处理程序数量越多,JavaScript的速度就越慢,尽管您需要100个处理程序才能真正看到差异
主要是,#1的影响最大。我认为在大多数情况下,试图在事件处理中获得性能提升是一种过早的优化。我看到的优化事件处理代码的唯一情况是,当您有一个每秒触发多次的事件(例如"滚动"answers"鼠标移动"事件)时。事件委派的另一个好处是,您不必清理将从文档树分离的DOM节点上的事件处理程序,从而允许浏览器垃圾收集内存。
(来自下面的评论)wvandell说:
事件委派的性能成本与事件的实际"冒泡"关系不大。。。将多个选择器委派给单个父级时会对性能造成影响。
这是真的,但是让我们想想感知到的性能。委派许多点击事件对用户来说不会很明显。如果委派像scroll
或mousemove
这样的事件,每秒可以触发50次以上(剩下20毫秒来处理该事件),则用户可能会察觉到性能问题。这又回到了我反对过早优化事件处理程序代码的论点。
许多点击事件可以在一个共同的祖先(如document.documentElement
)上毫无问题地进行委派。我会在那里委托一个"mousemove"事件吗也许吧这取决于其他情况,以及委托的"mousemove"事件是否足够响应。
- 在jQuery中创建向下滑动子菜单的最有效方法
- 使用Underscore.js修改json数组中所选元素的更有效方法
- 选择具有值数组的所有元素的最有效方法
- 将JSON存储和恢复到此Ionic应用程序的最有效方法
- 将javascript数组中的项移动到特定位置的有效方法
- 将JS对象数组转换为嵌套形式的最有效方法
- 隐藏具有特定类$.each、for等的元素的有效方法
- 什么's是调用具有可变参数的函数的有效方法
- 选择具有特定数据的所有 html 标记的最有效方法是什么 - [适当性],无论值如何
- 使用 jQuery 调用 PHP 端点的最有效方法
- 这是解析 Int 的有效方法吗?
- 在JavaScript中搜索数组映射的最有效方法
- 获取字符串中最后一个换行符的最有效方法是什么
- 什么's是在两个(或多个)阵列中找到匹配的细胞序列的最有效方法
- 什么's是在IE8+中添加元素的最有效方法
- 从任何jquery选择器字符串创建元素的最有效方法
- 在日期范围内查找丢失日期的最有效方法是什么
- 对区间[1,10^12]中的整数进行编码/解码的快速有效方法是什么
- 在条件(if)结构的条件语句中是否有定义变量的有效方法
- 在ASP.NET中使用JQuery UI自动完成的有效方法