jQuery – 在单个事件处理程序中组合选择器的问题

这是关于Patrick DW对我对这个问题的回答的评论。

多个选择器:识别触发器?

我的答案:

使用$(this)将获得被单击的元素..并且使用is()可以帮助您确定单击的内容。

$('a.button, span.xyz, a.another').click(function(e) { if ($(this).is("a.button")) { alert("a.button was clicked"); } else if ($(this).is("span.xyz")) { alert("span.xyz was clicked"); } else if($(this).is("a.another")) { alert("a.another was clicked); } }); 

帕特里克的评论

解决这个问题的方法是,它有效地将.delegate()遭受的低效率(针对选择器进行测试)与分配多个冗余处理程序的低效率相结合。 所以你得到两个世界中最糟糕的。

@John – 是的,将它们分解为单独的处理程序更有意义,并将它们共享的任何常用function放入可以在处理程序中调用的命名函数中。 这消除了在每次事件发生时运行.is()测试的需要,这可能是昂贵的。 测试被点击的元素有时是有益的。 这就是.delegate()的作用。 您将承受测试的费用,但会从分配的处理程序数量减少中获益


有人可以(详细地)解释帕特里克谈论的低效率吗? 为什么.is()在这种情况下代价高昂? 你.delegate()给出一个例子.delegate()

使用jQuery的.delegate()方法会受到性能损失,因为每次事件发生在具有委托处理程序的元素内部时,都需要进行类似的测试以确定哪个元素接收到了该事件。

这通常是值得的,因为通过使用.delegate()您(可能)无需为每个元素分配单独的处理程序。

使用上面的代码,您有分配多个处理程序的开销,并且您仍在运行需要测试的代码以查看接收到该事件的代码。

很难说.delegate()是否是您引用的问题的合适选择,但分配单个处理程序并避免if( $(this).is('something') )测试会更好。

如果原始OP代码的目的是为每个元素类型提供单独的function,但仍然让它们共享某些常用function的子集,那么最好将该通用function转换为它自己的命名函数并调用它。 这是一种更有效的方法。


编辑:

举个例子。 假设span.targetp.anothertaget元素是为了获取处理程序。 如您所见,容器中有许多元素。

使用选择器分配.click() ,最终会得到几个独立的事件处理程序。

 $('span.target').click(function() { /* do something with span */ }); $('p.anothertarget').click(function() { /* do something with p */ }); 

HTML

 
click me
i don't do anything

i get a click too

click me
i don't do anything

i get a click too

click me
i don't do anything

i get a click too

click me

这意味着jQuery需要管理所有这些元素的个体犯。 这是缺点。 好处是你不需要运行选择器来查看收到事件的内容。 它将始终由此表示(假设您为pspan使用了单独的函数。


使用.delegate() ,只为容器分配处理程序。 这是针对应该触发事件的每种类型的元素完成的。

如您所见,只分配了两个处理程序。 一个用于

元素,另一个用于 。 这显然减少了所需的处理程序数量。 但是费用是jQuery需要为container内发生的每个事件运行传递给.delegate()的选择器,以查看实际接收事件的元素类型

所以有一些给予和接受。

 $('#container').delegate('span.target','click',function() { /* do something with span */ }); .delegate('p.anothertarget','click',function() { /* do something with p */ }); 

HTML

 
click me
i don't do anything

i get a click too

click me
i don't do anything

i get a click too

click me
i don't do anything

i get a click too

click me

您之前的答案中代码的问题在于它有效地将第一个示例(分配了许多处理程序)的低效率与第二个示例(运行选择器)的低效率结合起来。 这就是我所说的两个世界中最糟糕的事情。

为什么效率会降低? 在这种情况下,主要是因为你将每个元素的每次点击额外3次转换为jQuery对象,其中:

 $("#container").delegate('a.button', 'click', function() { alert("a.button was clicked"); }).delegate('span.xyz', 'click', function() { alert("span.xyz was clicked"); }).delegate('a.another', 'click', function() { alert("a.another was clicked"); }); 

将绑定一次到容器(3个处理程序)并每次单击运行3个选择器中的每一个,而不是在所有绑定元素上具有n处理程序(元素数量)。 因此,绑定时间较短,整个处理程序的数量(假设有3个以上的元素)在一个大页面中低得多,因为它总是精确地附加3个。

此外,您不会产生初始$('a.button, span.xyz, a.another')选择器的成本,以便在开始时找到您需要的元素。

好吧,使用多重选择器的方式效率很低,表明该function足够通用,可用于所有选定的元素。

在我看来,最好单独选择每个选择器并附加一个click事件。 那对我来说也会更自然。

根据我上面的评论…(这可以更简单等)

  

elementA

elementB

或者让标签类型为您处理,如果这适合您的情况

 

elementA

elementB