jQuery .live()vs .on()方法,用于在加载动态html后添加click事件


216

我正在使用jQuery v.1.7.1,显然不赞成使用.live()方法。

我遇到的问题是,使用以下方法将html动态加载到元素中时:

$('#parent').load("http://..."); 

如果我尝试在之后添加click事件,则不会使用以下两种方法之一注册事件:

$('#parent').click(function() ...); 

要么

// according to documentation this should be used instead of .live()
$('#child').on('click', function() ...); 

实现此功能的正确方法是什么?它似乎只对.live()有效,但我不应该使用该方法。请注意,#child是动态加载的元素。

谢谢。


25
为什么说“据说已过时”?您不相信文档吗?

6
它不应该被弃用:它已被弃用。如果您查看jQuery doco,.live()它会告诉您如何重写.live()use .delegate().on()(取决于您是否在1.7+版本上)的现有用法。但是请注意,如果您添加一个带有.click()“ afterwards” 的处理程序,即在动态加载元素之后,它应该可以工作-唯一的问题是.click() 动态加载元素之前尝试分配。
nnnnnn 2012年

我将措辞改为“明显”,因为这基本上就是我的意思。无论如何,我现在知道,由于.load()事件是异步的,因此#child元素只能在成功处理程序中可靠地识别,这很有意义。
肖恩·托曼

Answers:


606

如果希望单击处理程序适用于动态加载的元素,则可以在父对象(不会动态加载)上设置事件处理程序,并为其选择一个与动态对象匹配的选择器,如下所示:

$('#parent').on("click", "#child", function() {});

事件处理程序将附加到该#parent对象,并且只要单击事件在源于的事件上冒泡#child,它就会触发您的单击处理程序。这称为委托事件处理(事件处理委托给父对象)。

这样做是因为#parent即使事件#child对象尚不存在,您也可以将事件附加到该对象,但是当事件后来存在并被单击时,click事件将冒泡到该#parent对象,它将看到它起源于#child和有一个事件处理程序可以单击#child并触发您的事件。


23
很好的解释!我以前从来没有想过要与之live()抗衡,on()但是今晚我决定再次尝试,而您的解释立即表明了我一直以来所缺少的东西。谢谢!
MikeSchinkel

6
一百万起。我开始使用淘汰赛,直到我意识到动态创建的子代在jQuery中是可行的,非常感谢。
布罗克·亨斯利

9
您应该考虑写一本书或其他东西:您的小文字比起有关« on() » 的jQuery文档中的整页内容对我更有帮助。非常感谢!
胆固醇

@ jfriend00您是否知道我们如何将相同的过程应用于悬停,非悬停的情况?是否有谈论此事的消息来源?
klewis's

@blackhawk-查看此答案。您可以注册mouseentermouseleave事件,并在处理程序中测试触发了哪个事件。jQuery的伪“悬停”事件不适用于委托。
jfriend00 '16

33

试试这个:

$('#parent').on('click', '#child', function() {
    // Code
});

$.on()文档中:

事件处理程序仅绑定到当前选定的元素;在您的代码调用时,它们必须存在于页面上.on()

#child当你调用元素不存在$.on()就可以了,因此事件未绑定(不同$.live())。#parent但是,确实存在,因此将事件绑定到此就可以了。

上面我的代码中的第二个参数充当“过滤器”,仅在事件冒泡至#parentfrom 时才触发#child


如果我在$ .load()方法之后调用$ .on()方法,那么为什么#child元素此时不存在?
肖恩·托曼

6
@SeanThoman-您必须从方法的成功处理程序中调用它.load()-而不是从.load()方法后的代码中调用它。 #child仅在成功处理程序实际执行时才被加载,而不是在之前执行。
jfriend00 2012年

即使如此,将您返回的所有数据插入DOM所花费的时间也意味着它可能无法连接。最近我一直在做很多单页应用程序工作,我的标准是var $ body = $('body'); $ body.on(“ event”,“ .element /#class”,function(e){}); 为了一切。1个选择器。不用担心加载了什么或没有加载什么。
lupos 2013年

21

$(document).on('click', '.selector', function() { /* do stuff */ });

编辑:我正在提供更多有关此工作原理的信息,因为...的话。在此示例中,您将在整个文档上放置一个侦听器。

当您找到click匹配的任何元素时.selector,该事件就会冒泡直到主文档(只要没有其他侦听器调用此event.stopPropagation()方法),该事件就会使事件冒泡到父元素。

您正在侦听来自与指定选择器匹配的元素的任何事件,而不是绑定到特定元素或元素集。这意味着您可以一次创建一个侦听器,该侦听器将自动匹配当前存在的元素以及任何动态添加的元素。

出于某些原因,这很聪明,包括性能和内存利用率(在大型应用程序中)

编辑:

显然,您可以监听的最接近的父元素更好,并且您可以使用任何元素代替,document只要您要监视事件的子元素在该父元素之内即可……但这确实没有任何事情要做这个问题。


23
他试过了$(element).on(...)。这是$(document).on(...,element,...)。不同的野兽。
cHao 2012年

@ArnoldRoa是的,性能更好。您不会在多个子级上拥有一个侦听器,无需在修改DOM时就重新应用该侦听器,并且默认情况下事件会通过DOM冒泡。运行一次,每个与选择器匹配的子级都将在单击时触发给定功能。
L422Y

@ L422Y在这里的评论非常有误导性。如果您对性能的影响感到好奇,请查看@ jfriend00@Jared 的回答
Gust van de Wal

@GustvandeWal怎么引起误解?如果您去发布100个$(this).on(...)而不是一次在父元素上监听事件,那么它的性能将大大提高。
L422Y

您只是在谈论附加事件。实际的性能瓶颈是太多的监听器触发了(例如您委派的监听器),而不是需要附加事件的大量元素。
古斯塔·范·德·沃尔

12

1.7中的.live()等效项如下所示:

$(document).on('click', '#child', function() ...); 

基本上,请在文档中查看单击事件并为#child对其进行过滤。


因为这就是事件处理程序附加到文档的方式(.live()确实如此)。
cHao 2012年

17
.live()现在不推荐使用的原因之一是,将所有实时事件处理程序放在文档对象上很不好。事情真的可能真的放慢。事件不仅必须一直冒泡到整个文档,而且您可能有很多事件处理程序可以浏览文档对象。其主要优点.on()是可以将其附加到与实际对象更近的父对象上,从而大大提高性能。所以...我不建议.on()与document对象一起使用。选择一个更近的父对象更好。
jfriend00 2012年

感谢您的澄清。值得一提的是,事件的性能已通过on()进行了很大的改进,因此,它应该比以前少了一个问题。如果附加到父项,我认为它必须是准备好文档的父项,否则您会遇到类似的问题。
杰瑞德(Jared)2012年

最糟糕的是,这确实模仿了不建议使用的.live()方法。但是,控制委派的能力当然是有利的。
Dan Lugg

9

我知道答案来得有点晚,但是我为.live()方法创建了一个polyfill。我已经在jQuery 1.11中对其进行了测试,并且看起来效果很好。我知道我们应该尽可能地实现.on()方法,但是在大型项目中,无论出于何种原因都无法将所有.live()调用转换为等效的.on()调用,以下可能工作:

if(jQuery && !jQuery.fn.live) {
    jQuery.fn.live = function(evt, func) {
        $('body').on(evt, this.selector, func);
    }
}

只需在加载jQuery之后且调用live()之前将其包括在内即可。


5

.on()适用于jQuery 1.7及更高版本。如果您使用的是旧版本,请使用以下命令:

$("#SomeId").live("click",function(){
    //do stuff;
});

8
OP说“我正在使用jQuery v.1.7.1”
Selvakumar Arumugam 2012年

1
@jfriend-为什么不发布自己的答案而不是拒绝我的投票?我每天都使用live()并使用所有低于1.6的版本,并且效果很好。我可以看到您擅长阅读文档,但有时将某些东西付诸实践对您有很大帮助。.live()工作。期。
马特·卡察特

5
@MatthewPatrickCashatt-我确实发布了自己的答案,但没有对您的答案投反对票-不要做出这样的盲目假设。1.7之前的版本.delegate().live()jQuery文档推荐并弃用的原因要好得多.live()。是的,.live()仍然可以,但是关于SO的答案应该推荐更好的做事方法。我在这里已经看过20次了。如果您.live()在此处将代码发布在SO上,它将被低估(除非是其他严重问题,否则我通常不会这样做)。
jfriend00 2012年

1
我没有拒绝投票,但是尽管.live()即使在1.7版中肯定也可以使用,但还是应该使用,.delegate()或者.on()因为.live()有充分的理由而被弃用。只要您注意到两个较新函数的语法更改都可以正常工作。
nnnnnn 2012年

1
@ jfriend00-你绝对正确。漫长的一天。我很抱歉。
马特·卡察特

3

我在项目中使用了“ live”,但我的一位朋友建议我应该使用“ on”而不是live。当我尝试使用它时,我遇到了您遇到的问题。

在我的页面上,我动态创建按钮,表行和许多dom内容。但是当我对魔术使用时消失了。

其他解决方案,例如像孩子一样使用它,每次单击都会调用您的函数。但是我找到了使它再次发生的方法,这是解决方案。

将代码写为:

function caller(){
    $('.ObjectYouWntToCall').on("click", function() {...magic...});
}

致电caller(); 在这样的页面中创建对象之后。

$('<dom class="ObjectYouWntToCall">bla... bla...<dom>').appendTo("#whereeveryouwant");
caller();

通过这种方式,当您并非每次单击页面时都会调用您的函数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.