【问题标题】:How do I attach events to dynamic HTML elements with jQuery? [duplicate]如何使用 jQuery 将事件附加到动态 HTML 元素? [复制]
【发布时间】:2010-11-24 10:43:20
【问题描述】:

假设我有一些 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>

在这种情况下,test4 链接会在用户点击a#anchor1 时创建。

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

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

【问题讨论】:

标签: javascript jquery events dhtml


【解决方案1】:

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

来自http://api.jquery.com/live/

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

对于 jQuery 1.7+,您可以使用 .on() 将事件处理程序附加到父元素,并将 a 选择器与 '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 元素)。

【讨论】:

  • 这个原本很出色的解决方案似乎对位于 Fancybox 中的 HTML 内容存在问题。我已经恢复为手动创建处理程序。我还没有尝试 iFrame 内容,所以 fanyxbos 的内容是正文的一部分,或者在我的情况下是文档变量。
  • live() 已弃用,而 .on() 出现了。但不清楚当我写$('selector').on('event', callback(){}) 时它不会工作。需要在 on() 中编写所需的选择器。 $(document).on('event', 'selector', callback(){})$('body').on('event', 'selector', callback(){})
  • 性能怎么样?和直接附加事件一样吗?
  • &lt;a&gt; 元素的href 地址设置为http://???? 时不起作用
  • $('body').on('each', 'myclass', function() { // do something }); @Sean 我试图在“类”的“每个”上做一些事情,但它不起作用。怎么了?
【解决方案2】:

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

$('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(),我的事件会被触发两次
  • @DKMudrechenko 这可能是因为您没有完全从中删除事件侦听器。
  • 这行得通,而且解释也很好。
【解决方案3】:

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

Sean's answer 显示了一个示例。

现已弃用:

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

来自文档:

将每个段落的文本显示在 每次点击都会提示框:

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

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

【讨论】:

  • 如果我的选择器需要成为其他元素的父元素怎么办?例如: $("p").parent(".myclass").live("click", ... 这似乎不适用于 live()。
  • 您可以尝试将其合并到单个查询中,例如 $("p:has(.myclass)").live("click",...)。注意:在某些情况下,直播不适用于所有活动。查看 livequery 插件以获得 live 不提供的支持。
  • 这不再是正确答案。自 jQuery 1.7 起,.live() 方法已被弃用。请改用.on()。让我们得到正确的答案[stackoverflow.com/a/9331127/363701] 一些赞成票。或@Matt - 你想更新你的答案吗?
【解决方案4】:

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

这是一个简单的例子:

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

【讨论】:

    【解决方案5】:

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

    $(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() 仍然有效。

    【讨论】:

      【解决方案6】:

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

      link text

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

      【讨论】:

      • live 已弃用。
      【解决方案7】:

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

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

      【讨论】:

        【解决方案8】:

        您想使用live() 函数。见the docs

        例如:

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

        【讨论】:

        • live 已弃用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多