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

标签 jquery

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

Multiple selectors: identify the triggering one?

我的答案:

使用 $(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 - 是的,将它们分解为单独的处理程序,并将它们共享的任何公共(public)功能放入可以从处理程序内部调用的命名函数中会更有意义。这消除了在每次事件发生时运行 .is() 测试的需要,这可能是昂贵的。有时测试被单击的元素可能会很有帮助。这就是 .delegate() 的作用。您承担了测试费用,但从分配的处理程序数量减少中获益


有人可以(详细地)解释帕特里克所说的低效率吗?为什么在这种情况下 .is() 成本高昂?您能否也给出一个使用 .delegate()

的示例

最佳答案

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

这通常是值得的,因为通过使用 .delegate()您(大概)避免了为每个元素分配单独的处理程序的需要。

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

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

如果原始OP代码的目的是为每个元素类型提供单独的功能,但仍然让它们共享公共(public)功能的一些子集,那么最好将该公共(public)功能滚动到其自己的命名函数中并调用它。这是一种更有效的方法。


编辑:

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

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

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

html

<div id='container'>
    <span class='target'>click me</span>             <!-- i get a handler -->
    <div>i don't do anything</div>
    <p class='anothertarget'>i get a click too</p>   <!-- i get a handler -->
    <span class='target'>click me</span>             <!-- i get a handler -->
    <div>i don't do anything</div>
    <p class='anothertarget'>i get a click too</p>   <!-- i get a handler -->
    <span class='target'>click me</span>             <!-- i get a handler -->
    <div>i don't do anything</div>
    <p class='anothertarget'>i get a click too</p>   <!-- i get a handler -->
    <span class='target'>click me</span>             <!-- i get a handler -->
</div>

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


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

如您所见,仅分配了两个处理程序。一个为<p>元素,另一个为 <span> 。这显然减少了所需处理程序的数量。但代价是 jQuery 需要运行您传递给 .delegate() 的选择器。对于 container 内发生的每个事件查看哪种类型的元素实际接收到了事件。

所以有一些让步。

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

html

<div id='container'>   <!-- i get a handler for the span.target -->
                       <!--             and for p.anothertarget -->
    <span class='target'>click me</span>             
    <div>i don't do anything</div>
    <p class='anothertarget'>i get a click too</p> 
    <span class='target'>click me</span>   
    <div>i don't do anything</div>
    <p class='anothertarget'>i get a click too</p> 
    <span class='target'>click me</span> 
    <div>i don't do anything</div>
    <p class='anothertarget'>i get a click too</p> 
    <span class='target'>click me</span>
</div>

您之前的答案中的代码的问题在于,它有效地将第一个示例的低效率(分配了许多处理程序)与第二个示例的低效率(运行选择器)结合在一起。这就是我所说的两全其美的意思。

关于jQuery - 在单个事件处理程序中组合选择器的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4315308/

相关文章:

jquery - 是否可以在 Twitter Bootstrap 弹出窗口中渲染图像?

jquery - 通过 jquery 动态添加 css 过滤器

javascript - CSS - 固定菜单按钮在滚动时显示

jquery - jQuery 条件语句的最佳语法是什么?

javascript - 调用时未播放随机音频列表

javascript - Codeigniter 分页 URI 上的 ESCAPE PAGE NUMBER

jquery - 响应式导航(移动菜单)在某些页面上不起作用

javascript - 我怎样才能让这个JS slider 每三秒自动播放一次

php - 关于 HTML5 或 Javascript 或 jQuery 中的图像上传验证

javascript - jQuery imgAreaSelect - 从表单传递的图像和区域选择问题