.on('click')和.click()的区别

592

以下代码有什么区别吗?

$('#whatever').on('click', function() {
     /* your code here */
});
并且
$('#whatever').click(function() {
     /* your code here */
});

有区别。使用 .on 会重新绑定 ajax 重新加载的内容,而 .click 不会。 - Teson
是的,有区别。使用.on会重新绑定ajax重新加载的内容,而.click则不会。 - Teson
13个回答

834

我认为,它们之间的区别在于使用模式。

我更喜欢使用.on而不是.click,因为前者可以使用更少的内存,并且适用于动态添加的元素。

考虑以下HTML:

<html>
    <button id="add">Add new</button>
    <div id="container">
        <button class="alert">alert!</button>
    </div>
</html>

我们是通过以下方式添加新按钮的

$("button#add").click(function() {
    var html = "<button class='alert'>Alert!</button>";
    $("button.alert:last").parent().append(html);
});

如果我们想要在点击时弹出警告框,可以使用 "click" 或 "on"。


当我们使用click

$("button.alert").click(function() {
    alert(1);
});

使用上述方法,会为匹配选择器的每个单独元素创建一个单独的处理程序。这意味着:

  1. 许多匹配的元素将创建许多相同的处理程序,从而增加内存占用。
  2. 动态添加的项目没有处理程序 - 也就是说,在上面的HTML中,除非重新绑定处理程序,否则新添加的"Alert!"按钮将无法工作。

当我们使用.on

$("div#container").on('click', 'button.alert', function() {
    alert(1);
});

使用上述方法,一个用于匹配选择器的单一处理程序可以处理所有匹配元素,包括动态创建的元素。


......使用.on的另一个原因

正如Adrien在下面评论中提到的,使用.on的另一个原因是命名空间事件。

如果你使用.on("click", handler)添加一个处理程序,通常可以使用.off("click", handler)将其删除,这将删除该处理程序。显然,这仅在您有对该函数的引用时才有效,那么如果没有呢?您可以使用命名空间:

$("#element").on("click.someNamespace", function() { console.log("anonymous!"); });

通过解绑实现

$("#element").off("click.someNamespace");

3
这段代码的含义是:当点击class为 alert 的 button 时,弹出一个警告框并显示数字 1。 - Matthew
14
如果我理解正确的话,使用on('click' ...)时另一个好处是可以使用命名空间,例如on('click.darkenallothersections' ...), 同时也可以有on('click.displaynextstep' ...),然后可以使用.unbind('click.displaynextstep')来仅解除所选的绑定。 - Adriano

43
以下两段代码在功能上没有区别。 .click(fn).on("click", fn) 的“快捷方式”(shortcut method)。从 .on() 的文档 中可以看到,一些事件有缩写方法,例如.click() 可以用来附加或触发事件处理程序。有关所有缩写方法的完整列表,请参见事件类别
请注意,.on().click() 不同之处在于,它具有通过传递 selector 参数创建委托事件处理程序的能力,而 .click() 则不会。当没有传递 selector 参数调用 .on() 时,其行为与 .click() 完全相同。如果想要进行事件委派,请使用 .on()

5
关于@andreister指出的性能问题,有何进展? - rubo77
@rubo77 最多可以忽略不计。我们只需要几毫秒的时间。 - Rory McCrossan
1
@RoryMcCrossan,对我来说这是很重要的事情-我正在寻找这个功能,因为我在页面上有多达3000个需要事件处理的问题。每个问题1毫秒会使我的页面执行时间延长3秒。你的评论对于大型列表并不实用。 - Randy
13
更大的问题是为什么你在一页上有3000个问题。如果你遵循良好的用户界面设计模式,你不应该在一页上提供那么多信息。可以考虑分页或惰性加载。甚至使用事件委托来为所有这些元素设置单个事件处理程序都会更好。 - Rory McCrossan
在jQuery中如何实现事件委托?使用.on()方法。 - gilly3
6
仅当使用event delegation并传递一个selector参数时,才会看到性能提升。如果您调用.on()而没有使用selector参数,则与使用.click()相比,不会有性能改进。 - gilly3

25

.on() 是jQuery 1.7推荐的事件绑定方式,它将.bind().live()的所有功能合并到一个函数中,根据传递的不同参数来改变行为。

在你编写的示例中,两者之间没有区别。都将处理程序绑定到#whateverclick事件上。 on() 提供了额外的灵活性,允许您将#whatever子元素触发的事件委托给单个处理程序函数,如果您选择这样做。

// Bind to all links inside #whatever, even new ones created later.
$('#whatever').on('click', 'a', function() { ... });

绑定到#whatever内的所有链接,即使稍后创建新链接也是如此。这不正是.live()所做的吗?此外,这似乎与其他答案相矛盾,其他答案说它只具有.click()的功能,因此不适用于未来事件。 - Ben G
3
@babonk - 这并不与其他答案相矛盾,因为正如Interrobang在第一段所说的那样,.on()可以做到.click()所能做的事情,并且还可以像.bind().live()一样使用-这取决于您使用的参数。 (其他答案也提到了这一点。)请注意,“绑定到#whatever内的所有链接”不是.live()所做的,而是.delegate()所做的。 .live()绑定到整个document而不是让你指定容器。还请注意,从jQuery 1.7开始,.live()已被弃用。 - nnnnnn
+1 代理事件: "通过选择在委托事件处理程序附加时保证存在的元素,您可以使用代理事件来避免频繁附加和删除事件处理程序。" http://api.jquery.com/on/ - jimasp

21

正如其他答案所提到的:

$("#whatever").click(function(){ });
// is just a shortcut for
$("#whatever").on("click", function(){ })

需要注意的是,.on() 支持多种其他参数组合,而 .click() 则不支持,这使得它能够处理事件委托(取代了.delegate().live())。

(显然,还有其他类似的 "keyup"、"focus" 等快捷方式方法。)

我发表额外答案的原因是提到在不带参数调用 .click() 时会发生什么:

$("#whatever").click();
// is a shortcut for
$("#whatever").trigger("click");

请注意,如果您直接使用.trigger(),则还可以传递额外的参数或jQuery事件对象,而.click()则无法实现。

我还想提到的是,如果您查看jQuery源代码(在jquery-1.7.1.js中),您将看到内部.click()(或.keyup()等)函数实际上将调用.on().trigger()。显然,这意味着您可以确保它们真正具有相同的结果,但这也意味着使用.click()会多出一点点开销——在大多数情况下,这没有任何问题或需要考虑的,但从理论上讲,在特殊情况下可能会有所影响。

编辑:最后,请注意,.on()允许您在一行中将多个事件绑定到同一个函数,例如:

$("#whatever").on("click keypress focus", function(){});

15

.click 事件只有在元素被渲染时才能起作用,并且仅附加到在DOM准备就绪时加载的元素上。

.on 事件是动态附加到DOM元素上的,这对于想要将事件附加到在ajax请求或其他情况下呈现的DOM元素上非常有用(在DOM准备就绪后)。


11

在这里,您将得到应用点击事件的不同方式列表。您可以根据需要选择适当的方法,或者如果您的点击不起作用,可以尝试其中的替代方法。

$('.clickHere').click(function(){ 
     // this is flat click. this event will be attatched 
     //to element if element is available in 
     //dom at the time when JS loaded. 

  // do your stuff
});

$('.clickHere').on('click', function(){ 
    // same as first one

    // do your stuff
})

$(document).on('click', '.clickHere', function(){
          // this is diffrent type 
          //  of click. The click will be registered on document when JS 
          //  loaded and will delegate to the '.clickHere ' element. This is 
          //  called event delegation 
   // do your stuff
});

$('body').on('click', '.clickHere', function(){
   // This is same as 3rd 
   // point. Here we used body instead of document/

   // do your stuff
});

$('.clickHere').off().on('click', function(){ // 
    // deregister event listener if any and register the event again. This 
    // prevents the duplicate event resistration on same element. 
    // do your stuff
})

2
$('.clickHere').off().on() 正是我所需要的。谢谢! - Tim Gottgetreu

9
不,没有。
on() 的重点在于其其他重载以及处理没有快捷方法的事件的能力。

9

它们看起来是相同的... 来自click()函数的文档:

这个方法是.bind('click', handler)的快捷方式

来自on()函数的文档:

从jQuery 1.7开始,.on()方法提供了所有所需的功能以附加事件处理程序。有关从旧版jQuery事件方法进行转换的帮助,请参见.bind()、.delegate()和.live()。要删除使用.on()绑定的事件,请参见.off()。


3
他们现在已经弃用了click()方法,最好使用on('click')方法。

1
据我从互联网和一些朋友那里了解到,on() 是在动态添加元素时使用的。但是当我在一个简单的登录页面中使用它,点击事件应该发送 AJAX 到 node.js,在返回时附加新元素,它开始调用多个 AJAX 调用。当我将其更改为 click() 时,一切都正常了。实际上,我以前没有遇到过这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接