如何使用jQuery将事件附加到动态HTML元素?[复制]

How do I attach events to dynamic HTML elements with jQuery? [duplicate]

提问人:frankadelic 提问时间:9/1/2009 最后编辑:daaawxfrankadelic 更新时间:4/28/2019 访问量:604042

问:

假设我有一些jQuery代码,该代码将事件处理程序附加到具有类的所有元素。.myclass

例如:

$(function(){
    $(".myclass").click( function() {
        // do something
    });
});

我的 HTML 可能如下所示:

<a class="myclass" href="#">test1</a>
<a class="myclass" href="#">test2</a>
<a class="myclass" href="#">test3</a>

这没有问题。 但是,请考虑这些元素是否在将来的某个时间写入页面。.myclass

例如:

<a id="anchor1" href="#">create link dynamically</a>
<script type="text/javascript">
$(function(){
    $("#anchor1").click( function() {
        $("#anchor1").append('<a class="myclass" href="#">test4</a>');
    });
});
</script>

在这种情况下,当用户单击 时,将创建链接。test4a#anchor1

该链接没有与之关联的处理程序,即使它有 .test4click()class="myclass"

基本上,我想编写一次处理程序,并将其应用于页面加载时存在的内容,以及稍后通过 AJAX / DHTML 引入的内容。知道我该如何解决这个问题吗?click()

JavaScript jQuery 事件 dhtml

评论

1赞 Satinder singh 8/17/2015
这是一篇关于如何为动态元素 goo.gl/zlEbnv 绑定点击事件的详细文章
0赞 Ram Patra 4/18/2016
纯 javascript only(vanilla js) 解决方案:stackoverflow.com/a/27373951/1385441
0赞 Prem 10/9/2016
这是答案 youtube.com/watch?v=unk-U_LQWuA
0赞 Yacine Rouizi 8/4/2021
也许这篇文章会有所帮助:dontrepeatyourself.org/post/......

答:

36赞 Matt Brunell 9/1/2009 #1

在 jQuery 1.7 之后,首选方法是 .on() 和 .off()

肖恩的回答就是一个例子。

现已弃用:

使用 jQuery 函数 .live().die()。可用于 jQuery 1.3.x

从文档中:

要在 每当单击时发出警报框:

$("p").live("click", function(){
  alert( $(this).text() );
});

此外,livequery 插件可以做到这一点,并支持更多事件。

评论

0赞 frankadelic 9/1/2009
如果我的选择器需要成为其他元素的父元素,该怎么办?例如:$(“p”).parent(“.myclass”).live(“click”, ...这似乎不适用于 live()。
0赞 Matt Brunell 9/1/2009
您可以尝试将其合并到单个查询中,例如 $(“p:has(.myclass)”).live(“click”,...)。注意:在某些情况下,直播功能并不适用于所有活动。查看 livequery 插件,了解 live 未提供的支持。
1赞 Zach Lysobey 2/17/2012
这不再是正确答案。从 jQuery 1.7 开始,不推荐使用 .live() 方法。请改用。让我们得到正确的答案[stackoverflow.com/a/9331127/363701]一些赞成票。或者@Matt - 你想更新你的答案吗?.on()
2赞 redsquare 9/1/2009 #2

如果您在 jQuery 1.3+ 上,请使用 .live()

将处理程序绑定到事件(如 单击)查看所有当前和未来 匹配元素。也可以绑定自定义 事件。

0赞 Adam Bellaire 9/1/2009 #3

您想使用该函数。请参阅文档live()

例如:

$("#anchor1").live("click", function() {
    $("#anchor1").append('<a class="myclass" href="#">test4</a>');
});

评论

0赞 Nardong Bagsik 1/13/2020
live 已弃用。
3赞 andres descalzo 9/1/2009 #4

将处理程序绑定到所有当前和未来匹配元素的事件(如单击)。还可以绑定自定义事件。

链接文本

$(function(){
    $(".myclass").live("click", function() {
        // do something
    });
});

评论

11赞 Francisco Corrales Morales 5/13/2014
live已弃用。
6赞 ScottE 9/1/2009 #5

如果要向 DOM 添加一堆锚点,请改为查看事件委派。

下面是一个简单的示例:

$('#somecontainer').click(function(e) {   
  var $target = $(e.target);   
  if ($target.hasClass("myclass")) {
    // do something
  }
});
1064赞 Sean 2/17/2012 #6

我正在添加一个新答案,以反映以后的jQuery版本中的更改。从 jQuery 1.7 开始,不推荐使用 .live() 方法。

从 http://api.jquery.com/live/

从 jQuery 1.7 开始,不推荐使用 .live() 方法。使用 .on() 附加事件处理程序。旧版本jQuery的用户应优先使用.delegate()而不是.live()。

对于 jQuery 1.7+,您可以使用 .on() 将事件处理程序附加到父元素,并将选择器与“myclass”组合作为参数传递。

查看 http://api.jquery.com/on/

所以而不是......

$(".myclass").click( function() {
    // do something
});

你可以写...

$('body').on('click', 'a.myclass', function() {
    // do something
});

这将适用于正文中带有“myclass”的所有标记,无论是已经存在还是以后动态添加的。

此处使用 body 标记,因为该示例没有更接近的静态周围标记,但发生 .on 方法调用时存在的任何父标记都将起作用。例如,将添加动态元素的列表的 ul 标签如下所示:

$('ul').on('click', 'li', function() {
    alert( $(this).text() );
});

只要 ul 标签存在,它就会起作用(尚不需要存在 li 元素)。

评论

0赞 8/12/2013
这个本来很出色的解决方案似乎存在 HTML 内容存在于 Fancybox 中的问题。我已恢复为手动创建处理程序。我还没有尝试过 iFrame Content,所以 fanyxbos 的内容是正文的一部分,或者在我的情况下是文档变量的一部分。
7赞 Satya Prakash 12/21/2013
live() 被弃用,而 .on() 来了。但目前尚不清楚当我写作时它是否行不通。需要在 on() 中写入所需的选择器。 或$('selector').on('event', callback(){})$(document).on('event', 'selector', callback(){})$('body').on('event', 'selector', callback(){})
4赞 ccov77 4/30/2014
性能如何?这与直接附加事件相同吗?
0赞 Mostafa 7/4/2016
当元素的地址设置为<a>hrefhttp://????
0赞 horse 9/3/2016
$('body').on('each', 'myclass', function() { // do something });@Sean我试图在“类”的“每个”上做一些东西,但它不起作用。怎么了?
5赞 i-- 3/29/2013 #7

您可以将所有元素的单击事件绑定到页面,无论它们是否已经在该页面上,或者它们是否会在将来的某个时间到达,如下所示:

$(document).bind('click', function (e) {
   var target = $(e.target);
   if (target.is('.myclass')) {
      e.preventDefault(); // if you want to cancel the event flow
      // do something
   } else if (target.is('.myotherclass')) {
      e.preventDefault();
      // do something else
   }
});

已经使用了一段时间。像魅力一样工作。

在 jQuery 1.7 及更高版本中,建议使用 in 代替 bind 或任何其他事件委派方法,但仍然有效。.on().bind()

122赞 Chandler Zwolle 7/16/2014 #8

有时这样做(得票最高的答案)并不总是足够的:

$('body').on('click', 'a.myclass', function() {
    // do something
});

这可能是一个问题,因为触发事件处理程序的顺序。如果您发现自己这样做,但由于处理顺序而导致问题。你总是可以把它包装成一个函数,当调用它时,它会“刷新”侦听器。

例如:

function RefreshSomeEventListener() {
    // Remove handler from existing elements
    $("#wrapper .specific-selector").off(); 

    // Re-add event handler for all matching elements
    $("#wrapper .specific-selector").on("click", function() {
        // Handle event.
    }
}

因为它是一个函数,所以每当我以这种方式设置侦听器时,我通常会在文档就绪时调用它:

$(document).ready(function() {
    // Other ready commands / code

    // Call our function to setup initial listening
    RefreshSomeEventListener();
});

然后,每当添加一些动态添加的元素时,请再次调用该方法:

function SomeMethodThatAddsElement() {
    // Some code / AJAX / whatever.. Adding element dynamically

    // Refresh our listener, so the new element is taken into account
    RefreshSomeEventListener();
}

希望这会有所帮助!

问候

评论

0赞 DKMudrechenko 3/23/2015
谢谢!无法让它与其他答案一起使用,您的解决方案就像一个魅力,但是如果我在添加动态元素后调用 RefreshSomeEventListener(),我的事件会触发两次
2赞 Ryan Steffer 4/13/2017
@DKMudrechenko 这可能是因为您没有从中完全删除事件侦听器。
0赞 Decoder.Ninja 2/27/2021
这行得通,也很好解释。
0赞 Dragos Vana 1/23/2023
这就是我一直在寻找的答案!