【问题标题】:Event Delegation in jQuery 1.4jQuery 1.4 中的事件委托
【发布时间】:2010-06-24 22:08:41
【问题描述】:

我有以下代码:

$("ul.relatedAlbums li").hover(function(){
    $(this).css({fontWeight:"bold"});
},
function(){
    $(this).css({fontWeight:"normal"});
});

我听说过关于事件委托和速度性能的好消息。使用 jQuery 的委托方法,我想它会是这样的:

$("ul.relatedAlbums").delegate("li", "hover", function(){
    $(this).css({fontWeight:"bold"});
},
function(){
    $(this).css({fontWeight:"normal"});
});

但是阅读文档,它说这种方法就像使用实时事件一样。而且我一直认为使用现场活动是低效。那么,有人能告诉我这方面的最佳做法吗?

【问题讨论】:

  • 仅供参考,hover 方法是一种将事件处理程序绑定到 mouseenter 和 mouseleave 事件的便捷方法,但性能差异应该很小。

标签: jquery performance hover event-delegation


【解决方案1】:

需要指出的是,.delegate() 目前实际上在内部使用 .live(),而贬低 .live() 将意味着一些框架工作。

除非您动态地向页面添加元素,否则您可以将其用作您的第一个示例。 .live() 和 .delegate 会在您有一个交互式页面时发挥作用,您可以在其中更改其中包含的元素。

编辑:致反对者:来自 jQuery 论坛: http://forum.jquery.com/topic/depreciating-live 引用此代码:

委托:函数(选择器,类型,数据,fn){ 返回 this.live(类型,数据,fn,选择器); },

我的观点是,如果合适,特定选择器将限制事件,并且仅选择 .delegate() 并不总是最好的,并且没有全局“总是这样做”。否则,为什么不将 .delegate() 用于所有不是最好的事情。

什么时候委托合适?当您的选择器确实有一个共同的父级时,例如 li 如 OP 所描述的那样经常使用,或者希望通过 .delegate() 绑定到一个共同的父级。不适用于单数的#selector,但对于存在多个或元素动态放置的类或元素选择器值得检查。

【讨论】:

  • 确实不正确。当我只能添加一个时,为什么要向 dom 添加 x 事件。通过使用事件委托,您不需要动态页面来获得性能优势。
  • @redsquare 这是从 1.4.2 分钟源中提取的:delegate:function(a,b,d,f){return this.live(b,d,f,a)}跨度>
  • 添加了一些注释以阐明我的观点。
【解决方案2】:

委托概念

如果一个父元素中有很多元素,并且您想处理它们的事件-不要将处理程序绑定到每个元素。相反,将signle处理程序绑定到它们的父项,并从 event.target 获取子项

那么,什么是 JavaScript 事件委托?

事件委托是一种简单的技术,通过它您可以将单个事件侦听器附加到父元素,该事件将为匹配选择器的所有子元素触发,无论这些子元素现在存在还是将来添加。

事件委托利用了 JavaScript 事件中两个经常被忽视的特性:事件冒泡和目标元素

什么是事件冒泡?

在事件冒泡中,事件首先被最里面的元素捕获和处理,然后传播到外部元素

什么是目标元素?

任何事件的目标元素都是原始元素,并存储在事件对象的属性中。

例子

<div id="container">
<ul id="list">
    <li><a href="http://domain1.com">Item 1</a></li>
    <li><a href="/local/path/1">Item 2</a></li>
    <li><a href="/local/path/2">Item 2</a></li>
    <li><a href="http://domain4.com">Item3</a></li>
</ul>
</div>

单击#list 组中的锚点时,我们希望将其文本记录到控制台。通常我们可以使用 .on() 方法直接绑定到每个锚点的点击事件:

// attach a directly bound event
   $( "#list a" ).on( "click", function( event ) {
    event.preventDefault();
    console.log( $( this ).text() );
    });

虽然这工作得很好,但也有缺点。考虑一下当我们在绑定了上面的监听器之后添加一个新的锚点会发生什么:

// add a new element on to our existing list
 $( "#list" ).append( "<li><a href='#'>Item 5</a></li>" )

如果我们点击我们新添加的项目,什么都不会发生。这是因为我们之前附加的直接绑定的事件处理程序。直接事件仅在调用 .on() 方法时附加到元素。在这种情况下,由于调用 .on() 时我们的新锚点不存在,因此它不会获取事件处理程序。

既然我们知道事件是如何冒泡的,我们可以创建一个委托事件:

// attach a delegated event
$( "#list" ).on( "click", "a", function( event ) {
event.preventDefault();
console.log( $( this ).text() );
});

请注意我们如何将 a 部分从选择器移动到 .on() 方法的第二个参数位置。第二个,选择器参数告诉处理程序监听指定的事件,当它听到它时,检查该事件的触发元素是否与第二个参数匹配。在这种情况下,触发事件是我们的锚标记,它与该参数匹配。由于匹配,我们的匿名函数将执行。现在,我们已将一个单击事件侦听器附加到我们的,它将侦听对其子锚点的点击,而不是仅将未知数量的直接绑定事件附加到现有锚标记。

事件委托有什么优势?

只给页面附加一个事件监听器,而不是五百个 动态创建的元素仍将绑定到事件处理程序。

希望这可以帮助您直观地了解事件委托背后的概念,并让您相信委托的力量! 访问:http://www.scriptcafe.in/2014/03/what-is-event-delegation-in-jquery.html

【讨论】:

    【解决方案3】:

    事件委托允许您不将事件绑定到单个元素,而是绑定到元素的公共父级。

    但是 .live() 在某种意义上是低效的,因为当事件冒泡时,它会冒泡记录,这可能与您可以手动指定的公共父级相距很多步。

    Delegate 通过允许您指定更接近的父级(不一定是文档)来解决此问题。

    简而言之,使用 .delegate(),它拥有 .live() 的所有优点并修复了有问题的方面。

    换句话说:.live() 默认冒泡到文档中。你可以指定一个更接近的上下文,这将消除它的低效率。 .delegate() 只是帮助你做到这一点的糖方法。

    【讨论】:

    • 明确地说,您是说在上面的两个示例中,“委托”比将悬停事件绑定到每个特定的 li 是 更好?我不需要直播方面。
    • 如果每个 ul 有多个 li,则委托会更好。如果你在 li 上绑定,你会绑定多次。如果使用委托,则在父级上绑定一次。这就是为什么它更好。
    猜你喜欢
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多