jQuery .live() vs .on() 加载动态 html 后添加点击事件的方法

IT技术 javascript jquery events dom handler
2021-01-21 04:06:21

我正在使用 jQuery v.1.7.1,其中 .live() 方法显然已被弃用。

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

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

如果我之后尝试添加点击事件,它不会使用以下任一方法注册该事件:

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

或者

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

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

谢谢。

6个回答

如果您希望单击处理程序为动态加载的元素工作,那么您可以在父对象(不会动态加载)上设置事件处理程序,并为它提供一个与您的动态对象匹配的选择器,如下所示:

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

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

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

一百万起我开始使用淘汰赛,然后我意识到这在 jQuery 中可以用于动态创建的孩子,非常感谢。
2021-03-24 04:06:21
@jfriend00 您是否知道我们如何将相同的过程应用于悬停、非悬停情况?有没有关于这个的消息来源?
2021-03-28 04:06:21
很好的解释!我以前从来没有想过live()vs.on()但今晚我决定再试一次,你的解释立即揭示了我一直以来遗漏的东西。谢谢!
2021-03-30 04:06:21
@blackhawk - 看到这个答案您可以注册mouseentermouseleave事件并在处理程序中测试触发了哪个事件。jQuery 的伪“悬停”事件不适用于委托。
2021-03-31 04:06:21
你应该考虑写一本书什么的:你的小文字对我来说比关于 « on() »的 jQuery 文档中的整页更有帮助非常感谢!
2021-04-06 04:06:21

尝试这个:

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

$.on()文档:

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

#child当您调用$.on()它时,您的元素不存在,因此事件不受约束(与 不同$.live())。#parent但是,确实存在,因此将事件绑定到该事件是可以的。

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

@SeanThoman - 您必须从方法的成功处理程序中调用它.load()- 而不是从.load()方法之后的代码中调用它#child只知道在成功处理程序实际执行时加载,而不是在此之前加载。
2021-03-18 04:06:21
即便如此,将您获得的任何数据插入 DOM 所需的时间也意味着它可能无法连接。我最近一直在做很多单页应用程序的工作,我的标准是 var $body = $('body'); $body.on("event", ".element/#class", function(e){}); 对于一切。1 选择器。不用担心加载或未加载什么。
2021-04-02 04:06:21
如果我在 $.load() 方法之后调用 $.on() 方法,那么为什么此时不存在 #child 元素?
2021-04-07 04:06:21

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

编辑:我提供了更多关于它是如何工作的信息,因为......词。在此示例中,您将在整个文档上放置一个侦听器。

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

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

这很聪明,原因有几个,包括性能和内存利用率(在大规模应用程序中)

编辑:

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

@ArnoldRoa 是的,性能更好。您不会有多个子级的侦听器,在修改 DOM 时不必重新应用侦听器,并且默认情况下事件会通过 DOM 冒泡。运行一次,每个与选择器匹配的子项将在单击时触发给定的函数。
2021-03-11 04:06:21
你只是在谈论附加事件。现实世界的性能瓶颈是触发了太多侦听器(例如您委托的侦听器),而不是需要附加事件的大量元素。
2021-03-17 04:06:21
他试过了$(element).on(...)这是$(document).on(...,element,...)不同的野兽。
2021-03-20 04:06:21
@GustvandeWal 它是如何误导的?如果你去发出一百美元(this).on(...) vs 在父元素上监听一次事件,它的性能要高得多。
2021-03-28 04:06:21
@L422Y 在这里的评论非常具有误导性。如果您对性能影响感到好奇,请查看@jfriend00@Jared的回答的评论
2021-04-09 04:06:21

1.7 中 .live() 的等价物如下所示:

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

基本上,查看文档中的点击事件并为#child 过滤它们。

因为这就是事件处理程序附加到文档的方式(方式.live()确实如此)。
2021-03-23 04:06:21
.live()现在不推荐使用的原因之一是将所有实时事件处理程序放在文档对象上是不好的。事情真的可以真的很慢。不仅事件必须一直冒泡到文档,而且您可能有很多事件处理程序要查看文档对象。的主要优点.on()是您可以将其附加到更接近实际对象的父对象并显着提高性能。所以......我不建议.on()与文档对象一起使用。选择更近的父对象要好得多。
2021-03-27 04:06:21
感谢您的澄清。值得一提的是,事件的性能已经通过 on() 得到了很大的提高,所以它应该不像以前那样成为一个问题。如果附加到父级,我认为它必须是存在于文档中的父级,否则您会看到类似的问题。
2021-03-29 04:06:21
在最坏的情况下,这确实模仿了已弃用的.live()方法;然而,控制委托的能力肯定是有利的。
2021-04-06 04:06:21

我知道答案有点晚了,但我已经为 .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() 之前包含它。