在我的页面上,用户点击某个元素以进行编辑。为了实现这一点,我将课程editable
分配给所有这些元素。
我应该如何听取所有这些元素的点击?目前,我正在这样做:
$lib.addEventListener(document.body, "click", function(event) {
if($lib.hasClass(event.target, "editable") {
// do stuff
}
});
其中$lib
是我使用的一个小JS库。
另一种方法是在每个元素上设置一个监听器,如下所示:
var editables = document.getElementsByClassName("editable");
for(var i = 0; i < editables.length; i++) {
$lib.addEventListener(editables[i], "click", editElement);
}
在我看来,第一种方式必须更好才能提高性能,因为它只是一个被监听的元素,但是可以通过将所有这些事件附加到body元素来降低性能吗?有没有其他考虑因素(例如事件处理的浏览器实现)我忽略哪些会建议以第二种方式进行?
答案 0 :(得分:6)
简答:绝对是第一种方式。事件委托更具性能,但在代码中需要额外的条件,因此它基本上是复杂性与性能权衡。
更长的答案:对于少量元素,添加单个事件处理程序可以正常工作。但是,随着您添加越来越多的事件处理程序,浏览器的性能开始下降。原因是监听事件是内存密集型的。
然而,在DOM中,事件从最具体的目标“冒泡”到最常见的触发任何事件处理程序。这是一个例子:
<html>
<body>
<div>
<a>
<img>
</a>
</div>
</body>
</html>
如果您点击<img>
标记,该点击事件将按此顺序触发任何事件处理程序:
document
object 事件委派是一种监听父级(比如<div>
)的技巧,而不是您关注的特定元素(比如<img>
) 。事件对象将具有一个target属性,该属性指向事件源自的特定dom元素(在本例中为<img>
)。
您的事件委派代码可能如下所示:
$(document).ready(function(){
$('<div>').on('click', function(e) {
// check if e.target is an img tag
// do whatever in response to the image being clicked
});
});
有关详情,请查看Dave Walsh的blog post on Event Delegation或duckduckgo“活动代表团”。
关于OP中代码示例的注释:在第一个示例中,target.hasClass('editable')
表示单击的特定内容必须具有可编辑的类才能执行if块。正如其中一位评论者指出的那样,这可能不是你想要的。你可能想尝试沿着这些方向尝试:
$(document).on('click', function(e) {
if ($(e.target).parents(".editable").length) {
// Do whatever
}
});
让我们稍微打破一下:
$(e.target)
- 点击页面上转换为jQuery的任何内容.parents(".editable")
- 找到点击元素的所有祖先,然后过滤为只包含“可编辑”类的元素.length
- 这应该是一个整数。如果为0,则表示没有父母具有“可编辑”类