【问题标题】:Difference between jQuery `click`, `bind`, `live`, `delegate`, `trigger` and `on` functions (with an example)?jQuery `click`、`bind`、`live`、`delegate`、`trigger` 和 `on` 函数之间的区别(带有示例)?
【发布时间】:2010-06-02 04:03:39
【问题描述】:

我已经阅读了jQuery official website上每个函数的文档,但是下面的函数之间没有这样的比较列表:

$().click(fn)
$().bind('click',fn)
$().live('click',fn)
$().delegate(selector, 'click', fn)
$().trigger('click') // UPDATED
$().on('click', selector ,fn); // more UPDATED

请避免任何参考链接。

以上所有功能究竟是如何工作的,在什么情况下应该首选哪个?

注意:如果还有其他功能具有相同功能或机制的,请详细说明。

更新

我还看到了$.trigger 函数。和上面的功能类似吗?

更多更新

现在.on 被添加到v1.7 中,我认为这个以某种方式涵盖了上述所有功能需求。

【问题讨论】:

  • @我喜欢 PHP,有时如果人们觉得这是一个无法通过手册回答的问题,或者看起来像是家庭作业问题,他们就会投反对票。不用担心,如果其他人觉得有用,他们会投票赞成。
  • @Typeoneerror--感谢支持,我已经阅读了手册,当我不明白明显的区别时,我在这里发布。
  • @I Like PHP - 编辑了这个问题以进行一些清理......这经常被问到,但很少以这种方式,它很容易成为有价值的谷歌资源。我同意类似这样的维基式条目会非常有帮助,我对此感到困惑,尤其是几乎每天都有.live().delegate(),+1 表示完全有效的问题。
  • @Nick Craver 感谢您的编辑,实际上我的英语不好(哈哈)。是否有任何关于我们如何在SO 上发布问题的 maunal/参考。不是靠经验来的
  • @我喜欢 PHP - 两者兼而有之,这里有一个很棒的全方位常见问题解答:meta.stackexchange.com/questions/7931 对于措辞/cmets,你才刚刚开始了解什么是最合适的,什么才是最好的有时传达您的想法,代码>任何描述的方式,使用正确的关键字,适当地标记,我想您在这里的时间越长,我看到很多海报随着时间的推移而改进。至于您的编辑,.trigger() 只是调用事件处理程序...我将在下面的答案中添加描述。

标签: javascript jquery


【解决方案1】:

在阅读本文之前,pull this list of events up in another page, the API itself is tremendously helpful, and all of what I'm discussing below is linked directly from this page

首先,.click(function) 实际上是.bind('click', function) 的快捷方式,它们是等价的。在将处理程序直接绑定到元素时使用它们,如下所示:

$(document).click(function() {
  alert("You clicked somewhere in the page, it bubbled to document");
});

如果此元素被替换或丢弃,则此处理程序将不再存在。此外,运行此代码时附加处理程序时不存在的元素(例如,选择器随后找到它)也不会获得处理程序。

.live().delegate() 类似相关,.delegate() 实际上在内部使用.live(),它们都侦听冒泡事件。 这适用于新元素和旧元素,它们以相同的方式冒泡事件。当您的元素可能发生变化时,您可以使用这些,例如添加新行、列表项等。如果您没有将保留在页面中并且在任何时候都不会被替换的父/共同祖先,请使用.live(),如下所示:

$(".clickAlert").live('click', function() {
  alert("A click happened");
});

但是,如果您在某处确实有一个没有被替换的父元素(因此它的事件处理程序不会再见),您应该使用.delegate() 处理它,如下所示:

$("#commonParent").delegate('.clickAlert', 'click', function() {
  alert("A click happened, it was captured at #commonParent and this alert ran");
});

这与.live() 的工作方式几乎相同,但事件在被捕获并执行处理程序之前冒泡的次数更少。这两种方法的另一个常见用途是说你的类在一个元素上发生了变化,不再匹配你最初使用的选择器......使用这些方法,选择器在事件发生时被评估,如果它匹配,处理程序运行......所以不再匹配选择器的元素很重要,它将不再执行。但是,使用.click(),事件处理程序被绑定在 DOM 元素上,它与用于查找它的任何选择器都不匹配的事实是无关紧要的......事件被绑定并且它一直保持到该元素消失,或通过.unbind() 删除处理程序。

.live().delegate() 的另一个常见用途是性能。如果您要处理很多 个元素,则将点击处理程序直接附加到每个元素是昂贵且耗时的。在这些情况下,设置一个单个处理程序并让冒泡完成工作会更经济,take a look at this question where it made a huge difference,这是一个很好的应用示例。


触发 - 更新问题

有两个主要的事件处理触发函数,they fall under the same "Event Handler Attachment" category in the API,它们是.trigger().triggerHandler().trigger('eventName') 内置了一些常用事件的快捷方式,例如:

$().click(fn); //binds an event handler to the click event
$().click();   //fires all click event handlers for this element, in order bound

You can view a listing including these shortcuts here.

至于区别,.trigger() 触发事件处理程序(但大多数时候不是默认操作,例如将光标放在点击的<textarea> 的正确位置)。它使事件处理程序按照它们被绑定的顺序发生(就像本机事件那样),触发本机事件操作,并在 DOM 中冒泡。

.triggerHandler() 通常用于不同的目的,在这里您只是试图触发绑定的处理程序,它不会导致本机事件触发,例如提交表格。它不会冒泡 DOM,也不是可链接的(它返回该事件的最后绑定事件处理程序返回的任何内容)。例如,如果您想触发focus 事件但实际上不关注对象,您只希望与.focus(fn) 绑定的代码运行,这将执行此操作,而.trigger() 将执行此操作以及实际关注元素并冒泡。

这是一个真实的例子:

$("form").submit(); //actually calling `.trigger('submit');`

这将运行任何提交处理程序,例如jQuery validation plugin,然后尝试提交<form>。但是,如果您只是想要验证,因为它是通过 submit 事件处理程序连接的,但之后不提交 <form>,您可以使用 .triggerHandler('submit'),如下所示:

$("form").triggerHandler('submit');

如果验证检查没有通过,插件会通过轰炸来阻止处理程序提交表单,但是使用这种方法我们不在乎它做了什么。无论它是否中止,我们都没有尝试提交表单,我们只是想触发它重新验证并且什么都不做。 (免责声明:这是一个多余的例子,因为插件中有一个.validate() 方法,但它是一个很好的意图说明)

【讨论】:

  • 非常彻底。一个小的更正:trigger 不会触发原生事件。本地是指使用fireEvent (IE) 或dispatchEvent (w3c) 模拟的事件。
  • @Crescent - 更新为不那么模棱两可,我的意思是它触发原生事件 actions,如表单提交、链接跟踪等...希望更新更清晰: )
  • @Nick 从我正在阅读的内容来看,您对live() 的看法似乎与您在这里给我的不同:stackoverflow.com/questions/3981762/… 使用@987654385 时“体重”仍然是一个问题吗@?
  • @yahelc - 是的,当然......这个答案是严格比较事件处理程序的选项及其特定目的。权重成本与初始绑定的数量与是否动态添加任何内容与初始选择器仍然是有效的问题。如果您的页面结构不是 那么 大,您没有 那么 很多事件,那么您很好......对重量的关注与重量成正比正在生成的结构的大小/深度和事件数量(.live() 调用所侦听的类型,例如click),因为它为每个事件运行选择器。
  • 在 jQuery 1.7 中,live() 已弃用,取而代之的是 $(document).on()。
【解决方案2】:

前两个是等价的。

// The following two statements do the same thing:
$("blah").click( function() { alert( "Click!" ); } );
$("blah").bind( "click", function() { alert( "Click!" ); } ); 

不过,第二个可用于同时绑定多个事件,方法是指定多个以空格分隔的事件名称:

$("blah").bind( "click mouseover mouseout", function() { alert( "Click! Or maybe mouse moved." ); } ); 

.live 方法更有趣。考虑以下示例:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").click( function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

脚本的第二行执行后,第二个链接也会有一个 CSS 类“myLink”。但它不会有事件处理程序,因为附加事件时它没有类。

现在考虑您希望它是另一种方式:每次带有类“myLink”的链接出现在页面上的某处时,您希望它自动具有相同的事件处理程序。当您有某种列表或表格时,这很常见,您可以在其中动态添加行或单元格,但希望它们都以相同的方式运行。您可以使用.live 方法,而不是每次都重新分配事件处理程序的所有痛苦:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").live( "click", function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

在本例中,第二个链接在获得“myLink”类后也会立即获得事件处理程序。魔法! :-)

当然,这不是字面意思。 .live 真正做的是将处理程序附加到指定的元素本身,而不是附加到 HTML 树的根(“body”元素)。 DHTML 中的事件具有“冒泡”这个有趣的特性。考虑一下:

<div> <a> <b>text</b> </a> </div>

如果你点击“文本”,那么首先 元素会得到一个“点击”事件。之后, 元素将获得一个“点击”事件。之后

【讨论】:

  • 准确地说,.live() 绑定到 document 而不是 &lt;body&gt; :) 你可以在这里查看演示,只需打开控制台查看:jsfiddle.net/aJy2B
  • 这样解释比较方便。 :-)
  • “body”部分足够公平,但是“一直到 元素”是错误的,事件继续从那里冒泡,这不是 .live() 处理程序所在的地方,在上面,document :) 你可以在这里看到一个演示:jsfiddle.net/S2VBX
【解决方案3】:

从 jQuery 1.7 开始,.live() 方法已被弃用。如果您使用的是

.live() 现在已替换为 .on()。

最好直接访问 jQuery 站点以获取更多信息,但这里是 .on() 方法的当前版本:

.on( events [, selector] [, data], handler(eventObject) )
.on( events-map [, selector] [, data] )

http://api.jquery.com/on/

【讨论】:

    【解决方案4】:

    $().click(fn)$().bind('click', fn) 乍一看是一样的,但$.bind 版本更强大有两个原因:

    1. $().bind() 允许您将一个处理程序分配给多个事件,例如,$().bind('click keyup', fn)
    2. $().bind() 支持命名空间事件 - 如果您只想删除(解除绑定)元素绑定到的某些事件处理程序,这是一个强大的功能 - 请阅读 Namespaced Events 了解更多信息。

    Live vs delegate:这已经在其他回复中得到了回答。

    【讨论】:

      【解决方案5】:

      这就是阅读 API 可能有所帮助的地方。但是,我知道我的头脑,所以你可以继续偷懒(耶!)。

      $('#something').click(fn);
      $('#something').bind('click',fn);
      

      这里没有区别(据我所知)。 .click 只是.bind('click' 的方便/辅助方法

      // even after this is called, all <a>s in
      // <div class="dynamic_els"> will continue
      // to be assigned these event handlers
      
      $('div.dynamic_els a').live(‘click’,fn);
      

      这是非常不同的,因为.live 将事件添加到您传入的选择器(您在这里没有)并在插入/删除节点时继续查看 DOM

      $('#some_element').delegate('td','click',fn);
      

      这只是因为您分配事件处理程序的方式而有所不同。 .delegate 以 DOM 事件冒泡为中心。基本原理是每个事件在 DOM 树中向上冒泡,直到到达根元素(documentwindow&lt;html&gt;&lt;body&gt;,具体记不清了)。

      无论哪种方式,您都将onclick 处理程序绑定到$('#some_element') 内的所有&lt;td&gt;s(您必须指定一个选择器,尽管您可以说$(document))。单击其中一个子项时,事件会冒泡到&lt;td&gt;。然后,您可以提取事件的源元素(jQuery 会自动为您执行此操作)。

      当有大量元素并且您只有几个(或一个中心)点可供这些事件通过时,这很有用。这样可以节省浏览器的工作量和内存,从而将这些事件处理程序整合到更少的对象中。

      【讨论】:

      • .live() also 可以消除事件冒泡,实际上.delegate().live() 的包装器,它只是添加上下文并绑定到元素除了document 以外的 来捕捉气泡。我认为您对冒泡处理程序如何工作的理解有点偏离(我认为这是 jQuery 1.4 最常被误解的方面)。该处理程序在您将其绑定到的元素上,因此无论您在其上调用.delegate()document(在.live() 的情况下为document),当事件冒泡到那里时,它都会检查目标看它是否匹配选择器,如果匹配则执行。
      猜你喜欢
      • 2012-06-24
      • 2011-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-25
      相关资源
      最近更新 更多