jQuery`Click`,`bind`,`live`,`delegate`,`trigger`和`on`函数之间的区别(有一个例子)?

时间:2010-06-02 04:03:39

标签: javascript jquery

我已阅读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 中,我认为这个在某种程度上涵盖了上述所有功能要求。

5 个答案:

答案 0 :(得分:161)

在您阅读本文之前,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()的另一个常见用途是效果。如果您正在处理 lot 元素,则将单击处理程序直接附加到每个元素是昂贵且耗时的。在这些情况下,设置单个处理程序并让冒泡工作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()方法,但它是一个很好的说明意图)

答案 1 :(得分:28)

前两个是等效的。

// 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>

如果您点击“文字”,那么首先&lt; b&gt;元素将获得“点击”事件。之后,&lt; a&gt;元素将获得“点击”事件。之后&lt; div&gt;元素将获得“点击”事件。依此类推 - 一直到&lt; body&gt;元件。这就是jQuery将捕获事件的位置,并查看是否有任何“实时”处理程序适用于首先导致事件的元素。整齐!

最后,.delegate方法。它只需要元素的所有子元素都符合给定的选择器,并为它们附加一个“实时”处理程序。看看:

$("table").delegate( "td", "click", function() { alert( "Click!" ); } );

// Is equivalent to:
$("table").each( function() {
    $(this).find( "td" ).live( "click", function() { alert( "Click!" ); } );
} );

有问题吗?

答案 2 :(得分:8)

从jQuery 1.7开始,不推荐使用.live()方法。如果您使用的是jQuery版本&lt; 1.7正式建议在.live()上使用.delegate()。

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

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

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

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

答案 3 :(得分:2)

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

  1. $().bind()允许您为多个事件分配一个处理程序,例如$().bind('click keyup', fn)
  2. $().bind()支持命名空间事件 - 如果您只想删除(取消绑定)元素绑定的某些事件处理程序,这是一个强大的功能 - 在 Namespaced Events 中阅读更多内容。
  3. Live vs delegate:其他回复中已经回答了这个问题。

答案 4 :(得分:1)

这是阅读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<html><body>,我记不清楚了)。

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

当有大量元素并且您只有这些事件将经历的少数(或一个中心)点时,这非常有用。这节省了浏览器的工作量和内存,以便将这些事件处理程序合并到更少的对象中。