jQuery .on does not work but .live does
由于从1.7版开始不推荐使用live()方法,因此我开始浏览源代码并将所有活动事件处理程序都转换为on()。 我的印象是,更改将非常简单,并且一切将像以前一样工作。 但是,我遇到了一些行为不正常的代码。
我有以下jQuery选择来绑定表标签的click事件...
1 2 3
| $('table.accordion-header').live("click", function ($e) {
// gobs of code
} |
...并且它工作得很好(即,即使在页面上发生异步回发之后,也会引发我的表标签click事件)。 但是如果我将代码更改为以下内容
1 2 3
| $('table.accordion-header').on("click", function ($e) {
// gobs of code
} |
那么在页面上发生任何异步回发后,将不再引发click事件。 请注意-click事件确实适用于所有异步回发,但之后将不再起作用。 那我在这里想念什么?
-
检查是否将其放在" $(document).ready()"函数类型中,或者是否在之前调用它并返回false。 有一种检查方法:$(table.accordion-header).trigger(click);
这样的问题已经回答了很多次,因为人们不太了解.on()的动态版本是如何工作的,这似乎很普遍。您正在使用静态形式的.on(),当您可能打算使用动态形式的.on()时,在调用.on()时对象必须存在,如下所示:
1 2 3
| $(someStaticParentObject).on("click", 'table.accordion-header', function ($e) {
// code
} |
将.live()替换为.on()是因为.on()通过指定动态对象的静态父对象来将事件处理程序附加到该对象,从而使您具有更好的性能,这比将其附加到document对象的效率更高。 .live()做了什么。我建议您阅读以前的答案(全部由我撰写),以了解有关如何最好地使用.on()的更多信息。这些答案还包括有关使用.on()的最有效方法的评论以及其工作方式的简要说明:
jQuery:关于vs直播
jQuery.on()是否可用于创建事件处理程序之后添加的元素?
jQuery的新on()方法与live()方法在性能上相比如何?
jQuery.bind()和jQuery.on()有什么区别?
为什么不将Javascript事件委托发挥到极致呢?
-
您提到附加到静态元素比文档更好。但是,如果您不了解特定的父母,则使用$(body).on与$(document).on有什么优势?
-
@PaulAlexander-首先,您应该将$(document.body)与$(document)进行比较。 Id总是选择DOM层次结构中最低的一种(在这种情况下为document.body),但实际上这两者之间并没有太大区别。
-
@ jfriend00,在许多情况下,附加到document是唯一的可能性,因为DOM在加载时(页面加载)在DOM中不存在其他对象。
-
@ md1337-通常,应该在页面加载之后而不是页面加载之前设置事件处理程序。在文档上放置大量事件处理程序在运行时效率很低。
-
@ jfriend00,仅供以后的读者参考,但是在页面加载时设置处理程序可以在页面加载100%之前使用页面功能。在长页面和AJAX控件的情况下特别有用。我有一个Web应用程序,其中包含一堆与AJAX回调关联的下拉列表,并且它们需要在它们出现的第二个时间内起作用。基本上,如果用户看到它,他们也必须能够使用它。我不能让用户弄乱下拉菜单,并且无法检测到它,因为页面仍在加载并且我的Javascript还没有启动。这使得UI非常敏感。
-
@ md1337-我重复我的评论,即在document对象上放置大量事件处理程序效率很低。这就是.live()完全从jQuery中删除的原因之一,因为这就是它的作用。如果您的网页加载时间太长,以至于您希望人们能够在页面其余部分加载之前与页面中间的下拉菜单进行交互,则有解决问题的有效方法。我仍然不建议您在文档对象上放置许多事件处理程序。
-
@ jfriend00,请告诉。如果有更好的方法,只要控件出现在页面上,我就会立即使用jQuery将回调绑定到change事件。我还可以辩称,由于页面正在下载过程中,因此所谓的效率低下是不相关的,这是真正的瓶颈,而不是jQuery解析DOM。
-
@ md1337-为什么页面加载时间如此之长,而对于大多数其他页面设计而言却并不重要,这对您来说是一个重要的考虑因素?
-
@ jfriend00我正在开发Web应用程序而不是网站。不同的世界。而且您仍然没有回答我的问题,您可能没有答案!再见。
-
@ md1337的答案是隐藏控件,并在页面加载后使它们出现。
-
@ md1337嗨,兄弟,这不是在这里说话的方式,我们是在这里学习和尊重,在某些情况下,也许只是在考虑其他人的意见
相当于
1 2 3
| $('table.accordion-header').live("click", function ($e) {
// gobs of code
} ); |
是
1 2 3
| $(document).on("click", 'table.accordion-header', function ($e) {
// gobs of code
} ); |
-
但是,如果您真正了解.on()的工作原理和用法,那么使用$(document).on()比使用$(document).on()更有效。替换.live()的一个主要原因是让人们使用它比这更有效率。我在下面的回答提供了更多详细信息。
-
是的,确实..我只是在使用OP提供的功能...还存在.delegate()用于更好的控制...
-
如果您对元素使用id,则单击添加到语法"#" $(document).on(" click",#id_of_the_element,function($ e){//代码块});
最好的表达方式就像jQuery在.live()和.on()功能上所说的那样:
在选择器" $(selector)"中,放入一个随页面加载的具体元素-不是动态的。
然后将辅助选择器放入指示"选择器"的方法中-可以动态创建该选择器。
1 2 3 4 5 6 7 8 9
| //so this..
$('table.accordion-header').live("click", function ($e) {
// gobs of code
});
//becomes this..
$('table').on("click",'.accordion-header', function ($e) {
// gobs of code
}); |
假设"表"当然已加载页面。
我也尝试将live()更新为on()遇到了麻烦,但是当有人向我展示了第一个父项或上下文选择器的工作原理时,我终于明白了。关键是确保第一个元素在文档对象模型中。
$(this)与.on()的工作方式也不明显。
1 2 3
| $(document).on("click", 'table.accordion-header', function ($e) {
// gobs of code
} ); |
在上面的示例中,函数代码中的$(this)将引用$('table.accordion-header')而不是您期望的$(document)。
进一步说明:.on()和$(this)
在jQuery 1.7.2源代码中,"实时"几乎指向"打开",因此此问题可能与"打开"功能无关。这需要排除。 on的选择器可能是个问题。
jQuery来源:
1 2 3 4
| live: function( types, data, fn ) {
jQuery( this.context ).on( types, this.selector, data, fn );
return this;
}, |
-
如果您更仔细地看这段代码并阅读其他答案,您会发现问题在于,它们将选择器table.accordion-header放置在与.on()等效的.live()的错误位置。
-
我在这里所说的是,"实时"和"在线"是相同的,"实时"指向"在线"。它是一个选择器问题,不存在也不存在。
-
当在原始问题中,发帖人认为将现场直播变成问题时,为什么还要标记我的答案无用。我必须指出,on == live,这是排除他最初对两者的误解的建议。
-
我认为,您没有回答他们的问题。您提供了一个可以看的地方的想法,即使对于OP实际应该看的地方也很模糊。您说"打开选择器可能是个问题"。他们需要更改选择器吗?他们应该如何解决?最好是评论,因为这不是答案。您甚至无法根据自己的写作风格确定这是正确的方向,而您没有告诉他们如何解决。
-
因此,试图为用户指出可能的答案的人应该受到惩罚吗?在我上方发布的那个人回答了这个问题吗?如果是这样,这与我的有什么不同?这是一个问答网站,所有可能导致答案的答案或可能的建议都是不错的,应予以考虑。我把他扔掉了吗?我相信不是。仅仅因为您的答案正确,其他所有答案都不正确。
-
抱歉,丹尼斯。我认为我们不需要将其转变为观点分歧。不能真正回答问题的评论(甚至是很有帮助的评论)也应该以评论而不是答案的形式发布。那就是SO想要的样子,以及他们认为Q&A格式最有效的方式。如果您对他们将选择器放在其他位置应该做的事情更加具体(例如Gabys答案),我会认为这是一个有效的答案。