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

IT技术 javascript jquery events dhtml
2020-12-22 01:00:50

假设我有一些 jQuery 代码将一个事件处理程序附加到所有具有 class 的元素.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>

在这种情况下,test4链接是在用户单击 时创建的a#anchor1

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

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

6个回答

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

来自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 元素存在)。

live() 已被弃用,而 .on() 来了。但不清楚当我写的$('selector').on('event', callback(){})时候它不会工作。需要在 on() 内编写所需的选择器。$(document).on('event', 'selector', callback(){})或者,$('body').on('event', 'selector', callback(){})
2021-02-09 01:00:50
$('body').on('each', 'myclass', function() { // do something });@Sean 我试图在“类”的“每个”上制作一些东西,但它不起作用。怎么了?
2021-02-14 01:00:50
性能怎么样?和直接附加事件一样吗?
2021-02-23 01:00:50
<a>元素的href地址设置为http://????
2021-02-24 01:00:50
这个出色的解决方案似乎在 Fancybox 中存在 HTML 内容的问题。我已经恢复到手动创建处理程序。我还没有尝试 iFrame Content,所以 fanyxbos 的内容是 body 的一部分,或者在我的情况下是 document 变量。
2021-03-05 01:00:50

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

$('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();
}

希望这会有所帮助!

问候,

谢谢!无法让它与其他答案一起工作,您的解决方案就像一个魅力,但是如果我在添加动态元素后调用 RefreshSomeEventListener(),我的事件将被触发两次
2021-02-18 01:00:50
@DKMudrechenko 这可能是因为您没有从中完全删除事件侦听器。
2021-03-01 01:00:50
这行得通,而且解释也很好。
2021-03-07 01:00:50

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

肖恩的回答给出了一个例子。

现在已弃用:

使用 jQuery 函数.live().die(). 在 jQuery 1.3.x 中可用

从文档:

要在每次单击时在警告框中显示每个段落的文本:

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

此外,livequery插件会执行此操作并支持更多事件。

您可以尝试将其合并到单个查询中,例如 $("p:has(.myclass)").live("click",...)。注意:在某些情况下,live 并不适用于所有事件。查看 livequery 插件以获取 live 不提供的支持。
2021-02-24 01:00:50
这不再是正确的答案。.live() 方法从 jQuery 1.7 开始被弃用。使用.on()来代替。让我们得到正确的答案 [ stackoverflow.com/a/9331127/363701]一些赞成票。或者@Matt - 你想更新你的答案吗?
2021-03-03 01:00:50
如果我的选择器需要成为其他元素的父元素怎么办?例如: $("p").parent(".myclass").live("click", ... 这似乎不适用于 live()。
2021-03-06 01:00:50

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

这是一个简单的例子:

$('#somecontainer').click(function(e) {   
  var $target = $(e.target);   
  if ($target.hasClass("myclass")) {
    // do something
  }
});

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

$(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 及更高版本中,建议使用.on()代替 bind 或任何其他事件委托方法,但.bind()仍然有效。