jQuery: .click()和.on("click")之间的区别

26

我通常使用

$(selector).click(...

但是有些人建议我使用这个:

$(selector).on("click", function(...

或者 $(selector).live("click"...(已弃用)

我阅读了手册,但作为初学者,我无法理解。我被他们使用的所有术语搞混了。我仍然不知道为什么要使用.on(),也不知道它与.live()有什么区别。
http://api.jquery.com/on/


1
从文档中可以得知:"自jQuery 1.7版本起,.on()方法提供了所有必需的功能来绑定事件处理程序。如果需要旧版本jQuery事件方法的等效方法,请参见 .bind()、.delegate() 和 .live() 方法。" - Felix Kling
3个回答

34

每个事件最终都与DOM中的某些元素绑定。在使用.bind的情况下,您直接将事件绑定到jQuery对象中的元素(或多个元素)上。例如,如果jQuery对象包含100个元素,则将绑定100个事件监听器。

对于.live.delegate.on,仅绑定单个事件侦听器,通常位于DOM树中的顶层节点之一:documentdocument.documentElement(即<html>元素)或document.body。因为DOM事件会冒泡到树上,所以附加到body元素的事件处理程序实际上可以接收源自页面上任何元素的单击事件。因此,不必绑定100个事件,只需绑定一个事件。

对于少量元素(比如小于五个),直接绑定事件处理程序可能更快(尽管性能不太可能成为问题)。对于大量元素,请始终使用.on

.on的另一个优点是,如果您向DOM添加新元素,则无需担心将事件处理程序绑定到这些新元素上。例如,请参考HTML列表:

<ul id="todo">
  <li>buy milk</li>
  <li>arrange haircut</li>
  <li>pay credit card bill</li>
</ul>

接下来是一些 jQuery 代码:

// Remove the todo item when clicked.
$('#todo').children().click(function () {
  $(this).remove()
})

现在,如果我们添加一个待办事项呢?

$('#todo').append('<li>answer all the questions on SO</li>')

点击此待办事项不会将其从列表中删除,因为它没有绑定任何事件处理程序。如果我们使用 .on 而不是 .click,新项目将无需额外的工作即可正常工作。下面是使用 .on 版本的代码:

$('#todo').on('click', 'li', function (event) {
  $(event.target).remove()
})

你为什么使用 $(event.target).remove(); 而不是 **$(this).remove();**?另外,我在 JSFiddle 上尝试了一下,但无法使其工作 :-( [http://jsfiddle.net/u6qWs/1/] - Omar
@Omar 的观点很好,关于event.target。在我写这篇文章的时候,我不确定在传递给.on的事件处理程序中this的绑定情况。刚刚阅读了该方法的文档,我现在意识到在这种情况下thisevent.type将引用相同的对象(但不是所有情况都是如此)。 - davidchambers
@Omar,.on方法是在jQuery 1.7中添加的,该版本刚刚发布。您的fiddle使用的是jQuery 1.6.4。 - davidchambers
@davidchambers 哎呀!我已经修复了这个示例。谢谢你指出问题。它现在可以运行了![http://jsfiddle.net/u6qWs/4/] 顺便说一下,你的示例很棒,但是每行最后缺少分号";"。 - Omar
使用click()方法在子元素上(“$('#todo').children()”)进行的一些观察表明,该方法将删除子元素对象本身。因此,没有子元素对象=没有事件对象。另一方面,在#todo上使用.on方法不会删除#todo对象,而是针对所有<li>元素进行操作..我认为这是应该提出的重点..on click方法可以将元素作为参数。 - repzero

12

使用普通的 .click(... 如果选择器的目标在页面中被动态改变(例如通过一些 AJAX 响应),那么你需要再次指定这个行为。

.live(... 中,行为会自动重新应用到选择器上。

.on(... 是非常新的(jQuery 1.7)。它可以使用委托事件来覆盖 live 场景,这是一种更快的方式来附加行为。


那么,如果我克隆一个元素,或者使用ajax动态创建内容,如果我使用**.click()在新内容上不起作用,但是使用.on("click")**它会起作用?我认为这被称为绑定方法/事件? - Omar
此外,.on() 可以使用映射同时附加多个事件。 - Pedram Behroozi
1
@Omar:是的,假设您已经正确地进行了委托。例如,如果您正在谈论表格中的 tr,则需要执行 $("#myTable").on("click", "tr", ...。请参阅 http://api.jquery.com/on/。 - cherouvim
@pedram-behroozi 我甚至不知道 jQuery map 是什么...它使用 GPS 吗?:p. 啊啊啊...如何使用 map 同时附加多个事件? - Omar
@cherouvim 我看了api.jquery.com/on...但是像我解释的那样,我是一个初学者,不理解他们使用的所有术语。我更加困惑了 :-( - Omar
尝试寻找jQuery教程,还可以考虑购买一本入门书。 - cherouvim

8
唯一的区别在于 .click() 只会应用于文档对象模型中已经存在的指定选择器的元素(仅限于已经存在的)。
.on(selector ,"click",callback); 会应用于所有与该选择器匹配的元素,包括未来出现的元素。让我举个例子:
$('p').click(function(){
$(this).next('<p>this is a copy of the previous paragraph </p>');
});

如果您点击写着“这是前一个段落的副本”的那个段落(新段落),您将无法得到想要的结果,即在所点击的段落旁边添加一个新段落,因为该段落最初并不存在。
但是,如果您使用

标签来结束前一个段落,并开始一个新段落,您就可以成功地添加一个新段落了。
$('p').on("click",function(){
$(this).next('<p>this is a copy of the previous paragraph </p>');
});

你会得到你想要的(因为 .on.delegate 甚至可以在新元素中找到匹配项)。

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