jquery .live('click') vs .click()

61

我想知道是否有任何情况下最好使用.click(function {...});而不是.live('click', function {...});

从我的理解来看,.live()选项似乎是更好的选择,因此在几乎所有情况下,我都使用它而不是普通的.click(),特别是考虑到我的许多代码是异步加载的。

编辑: 此问题的另一个部分是,如果我异步加载了所有javascript代码,那么.click()仍将捕获dom中已经存在的所有元素。对吗?


4
注意:live() 已经被弃用。 - UpTheCreek
4
不,它已经过时了 ;) - Jay
3
live()方法在jQuery 1.7版本中被弃用,在1.9版本中被移除。 - SHEKHAR SHETE
11个回答

147

有时候你可能只想显式地将点击处理程序分配给已经存在的对象,并以不同方式处理新对象。但更常见的情况是,live() 并不总是有效。它无法与像下面这样的链式 jQuery 语句一起使用:

$(this).children().live('click',doSomething);

由于事件冒泡的方式,它需要一个选择器才能正常工作。

编辑:有人刚刚点赞了这个问题,所以显然还有人在关注。我应该指出,livebind 都已经被弃用。你可以使用.on() 来执行两者,这在我看来是一种更清晰的语法。要替换 bind

$(selector).on('click', function () {
    ...
});

并且替换 live

$(document).on('click', selector, function () {
    ...
});

你可以使用包含所需点击元素的任何 jQuery 对象来代替 $(document),但在调用它时,相应的元素必须存在。


7
仅作为旁注:自jQuery 1.7起,它们已被弃用。在jQuery 1.4.3以上的版本中应使用代理(delegate),如果版本较低,则应使用live。 - Luis Lobo Borobia
7
为了让更多人避免错误的事情,更新两年前的答案是很有价值的,这将指引他们朝着正确的方向前进。+1 - Immutable Brick

13

(Note 29/08/2017: live已经在许多版本中被弃用,并在v1.9中移除。 delegate在v3.0中被弃用。在这两种情况下,应改用on的委托签名 [下面也有相关内容].)


live通过捕获事件并将其沿DOM一直冒泡到文档根时发生,并查看源元素。 click通过在元素本身上捕获事件来发生。因此,如果您正在使用live,并且其中一个祖先元素直接挂钩事件(并阻止它继续冒泡),则永远不会在您的元素上看到该事件。而通常,最接近事件(点击或其他)的元素首先抓住它,live和非live事件的混合可以以微妙的方式改变它。

例如:

jQuery(function($) {

  $('span').live('click', function() {
    display("<tt>live</tt> caught a click!");
  });

  $('#catcher').click(function() {
    display("Catcher caught a click and prevented <tt>live</tt> from seeing it.");
    return false;
  });

  function display(msg) {
    $("<p>").html(msg).appendTo(document.body);
  }

});
<div>
  <span>Click me</span>
  <span>or me</span>
  <span>or me</span>
  <div>
    <span>I'm two levels in</span>
    <span>so am I</span>
  </div>
  <div id='catcher'>
    <span>I'm two levels in AND my parent interferes with <tt>live</tt></span>
    <span>me too</span>
  </div>
</div>
<!-- Using an old version because `live` was removed in v1.9 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js">
</script>

我建议您在可以的情况下使用 delegate 而不是 live,这样您可以更全面地控制范围;使用 delegate,您可以控制捕获冒泡事件的根元素(例如,live 基本上是使用文档根作为根的 delegate)。此外,建议避免(如果可能)使用非委托、非实时事件处理与 delegatelive 进行交互。
几年后的今天,您将不再使用 livedelegate,而是使用 on 的委托签名,但概念仍然相同:事件被挂钩到您在其上调用 on 的元素上,但只有后代匹配事件名称后给定的选择器时才会触发该事件:

jQuery(function($) {

  $(document).on('click', 'span', function() {
    display("<tt>live</tt> caught a click!");
  });

  $('#catcher').click(function() {
    display("Catcher caught a click and prevented <tt>live</tt> from seeing it.");
    return false;
  });

  function display(msg) {
    $("<p>").html(msg).appendTo(document.body);
  }

});
<div>
  <span>Click me</span>
  <span>or me</span>
  <span>or me</span>
  <div>
    <span>I'm two levels in</span>
    <span>so am I</span>
  </div>
  <div id='catcher'>
    <span>I'm two levels in AND my parent interferes with <tt>live</tt></span>
    <span>me too</span>
  </div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


10

在设置事件时,与 .click 相关联的所有对象必须存在。

例如(伪代码)可以使用 $("body").append() 进行附加操作。

append('<div id="foo" class="something">...</div>');
$("div.something").click(function(){...});
append('<div id="bar" class="something">...</div>');

点击可以运作于foo但无法运作于bar

例2:

append('<div id="foo" class="something">...</div>');
$("div.something").live("click",function(){...});
append('<div id="bar" class="something">...</div>');

点击事件对于 foo 和 bar 都起作用。

使用 .live('click'...,您可以在创建事件后动态添加更多的对象,并且点击事件仍将起作用。


很酷,这就是为什么我正在使用.live。我很好奇是否有其他方面的好处。 - kalpaitch
1
不会投反对票,但这并不是被问到的问题。不过解释得很好。 - Thomas Clayson
实际上,这正好回答了我来到这里的问题。我现在明白为什么我的 .click 失败了,而我的 .live("click",...) 却可以工作——我有一个排序问题,在调用 .click 时还没有创建 .click 需要的元素,因此我的事件没有被调用,而 .live 不关心排序,因此可以工作。 - Rob

6

"live"在动态生成代码时是必需的。 只需查看以下示例:

$("#div1").find('button').click(function() {
    $('<button />')
     .text('BUTTON')
     .appendTo('#div1')
})
$("#div2").find('button').live("click", function() {
    $('<button />')
     .text('BUTTON')
     .appendTo('#div2')
})
button {
  margin: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<div id="div1">
  <button>Click</button>
</div>
<div id="div2">
  <button>Live</button>
</div>

没有使用"live"时,点击事件仅在您单击第一个按钮时发生。使用"live"后,动态生成的按钮也可以触发点击事件。


很棒的例子来解释! - Manish Singh

4

如果您没有动态添加元素,请始终使用click

live通过向文档根添加事件侦听器并侦听冒泡事件来工作。另一种选择是delegate,它的工作方式相同,但将事件处理程序绑定到指定的元素。
这样,事件不必冒泡整个DOM并且可以更早地被捕获。


3

.live() 用于在初始页面加载后添加元素。假设您有一个按钮,在页面加载后通过 AJAX 调用添加。这个新按钮将无法使用 .click(),因此您必须使用 .live('click')。


.live() - 版本已弃用:1.7,已移除:1.9!请使用.on() - Andrei Krasutski

1
据我所知,live() 的关键区别在于它会监视与您正在处理的选择器匹配的新 DOM 元素,而 click()(或 bind('click'))则附加事件钩子并完成操作。
考虑到很多代码是异步加载的,使用 live() 会让您的生活变得更加轻松。如果您不确定正在加载的代码,但确实知道要监听哪种元素,则使用此函数是非常明智的选择。
就性能提升而言,使用 live() 的一种替代方法是实现 AJAX 回调函数以重新绑定事件钩子。
var ajaxCallback = function(){
 $('*').unbind('click');
 $('.something').bind('click', someFunction);
 $('.somethingElse').bind('click', someOtherFunction);
}

您需要正确跟踪您的事件钩子,并确保此函数重新绑定了正确的事件。

p.s. Ajax 方法 .get()、.post()、.load() 和 .ajax() 都允许您指定回调函数。


1

由于'live'会处理未来与当前选择器匹配的元素的事件,因此您可以选择单击(click),因为您不希望发生这种情况 - 您只想处理当前选择的元素。

另外,我怀疑(尽管没有证据)使用'click'比'live'效率略高。


0

除了T.J. Crowders answer,我还添加了一些处理程序-包括较新的.on(...)处理程序到片段中,以便您可以看到哪些事件被隐藏,哪些事件没有被隐藏。

我发现.live()不仅已经过时,而且自jQuery 1.9.x以来已被删除。但是其他的,即
.click.delegate/.undelegate.on/.off
仍然存在。

还要注意,在Stackoverflow上有更多关于这个主题的讨论。

如果您需要修复依赖.live的旧代码,但又需要使用新版本的jQuery(>1.8.3),则可以使用此片段进行修复:

// fix if legacy code uses .live, but you want to user newer jQuery library
if (!$.fn.live) {
    // in this case .live does not exist, emulate .live by calling .on
    $.fn.live = function(events, handler) {
      $(this).on(events, null, {}, handler);
    };
}

以下代码片段意图是扩展 T.J. 的脚本,让您可以立即尝试绑定多个处理程序的效果 - 请运行这个代码片段并单击下面的文本:

jQuery(function($) {

  // .live connects function with all spans
  $('span').live('click', function() {
    display("<tt>live</tt> caught a click!");
  });

  // --- catcher1 events ---

  // .click connects function with id='catcher1'
  $('#catcher1').click(function() {
    display("Click Catcher1 caught a click and prevented <tt>live</tt> from seeing it.");
    return false;
  });

  // --- catcher2 events ---

  // .click connects function with id='catcher2'
  $('#catcher2').click(function() {
    display("Click Catcher2 caught a click and prevented <tt>live</tt>, <tt>delegate</tt> and <tt>on</tt> from seeing it.");
    return false;
  });

  // .delegate connects function with id='catcher2'
  $(document).delegate('#catcher2', 'click', function() {
    display("Delegate Catcher2 caught a click and prevented <tt>live</tt> from seeing it.");
    return false;
  });

  // .on connects function with id='catcher2'
  $(document).on('click', '#catcher2', {}, function() {
    display("On Catcher2 caught a click and prevented <tt>live</tt> from seeing it.");
    return false;
  });

  // --- catcher3 events ---

  // .delegate connects function with id='catcher3'
  $(document).delegate('#catcher3', 'click', function() {
    display("Delegate Catcher3 caught a click and <tt>live</tt> and <tt>on</tt> can see it.");
    return false;
  });

  // .on connects function with id='catcher3'
  $(document).on('click', '#catcher3', {}, function() {
    display("On Catcher3 caught a click and and <tt>live</tt> and <tt>delegate</tt> can see it.");
    return false;
  });

  function display(msg) {
    $("<p>").html(msg).appendTo(document.body);
  }

});
<!-- with JQuery 1.8.3 it still works, but .live was removed since 1.9.0 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js">
</script>

<style>
span.frame {
    line-height: 170%; border-style: groove;
}
</style>

<div>
  <span class="frame">Click me</span>
  <span class="frame">or me</span>
  <span class="frame">or me</span>
  <div>
    <span class="frame">I'm two levels in</span>
    <span class="frame">so am I</span>
  </div>
  <div id='catcher1'>
    <span class="frame">#1 - I'm two levels in AND my parent interferes with <tt>live</tt></span>
    <span class="frame">me too</span>
  </div>
  <div id='catcher2'>
    <span class="frame">#2 - I'm two levels in AND my parent interferes with <tt>live</tt></span>
    <span class="frame">me too</span>
  </div>
  <div id='catcher3'>
    <span class="frame">#3 - I'm two levels in AND my parent interferes with <tt>live</tt></span>
    <span class="frame">me too</span>
  </div>
</div>


0

请记住,“live”仅适用于“jQuery 1.3”或更高版本

在“jQuery 1.4.3”或更高版本中使用“delegate”

而在“jQuery 1.7+”或更高版本中使用“on”

$( selector ).live( events, data, handler ); // jQuery 1.3+
$( document ).delegate( selector, events, data, handler ); // jQuery 1.4.3+
$( document ).on( events, selector, data, handler ); // jQuery 1.7+

从jQuery 1.7开始,.live()方法已被弃用。

请查看http://api.jquery.com/live/

祝好, Fernando


...而现在,自从jQuery版本1.9.x起,**.live**方法已被删除。 - Matt

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