jQuery事件处理程序仅适用于第一个元素。

3

我似乎无法弄清楚为什么只有第一个元素调用我的事件处理程序来显示警报。我在Stack Overflow上找到了其他类似的问题,这些问题涉及使用ID而不是类,但这不是我的问题。

当我点击第一个元素旁边的“x”时,它按预期显示警报,但对于通过附加按钮动态添加的其他元素则无法实现。

这是一个最小但完整的示例:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>test</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>
<script type="text/javascript">

$(document).ready(function() {

   $(function() {

     $(".append").click(function(){

      $('.container').append('<div class="box"></div>')
      $('.box:last').append('<div class="text"><span>ABCDEFG</span><br/></div>')
      $('.box:last').append('<a href="#" class="test">x</a>')

     });

      $("a.test").click(function() {
      alert("works only for the first item in the list");


     });


   });


});

</script>
   <style>
      .box {
          padding:3px;
          margin-bottom:3px;
          border-bottom:2px solid #fff;
          width:550px;
      }
      .box:hover{background-color:#fff;}

      #container {
          position:relative;
      }

      .text {
          float:left;
          width:300px;
          font-size:13px;
      }
      .text span {
          font-size:18px;
          line-height:23px;
          font-weight:700;
      }

   </style>
</head>

<body>

   <div class="container">

     <input type="button" class="append" value="Append">

      <div class="box">
     <div class="text"><span>ABCDEFG</span></div>
     <a href="#" class="test">x</a>
     </div>

   </div>

</body>
</html>
3个回答

3

更改

$("a.test").click(function() {

为了

$("a.test").live('click', function() {

只有第一个元素起作用的原因是,当附加 click 事件时,页面上只有一个 <a> 元素。您需要显式地将点击事件处理程序添加到创建的每个链接,或者改用 live 事件。了解更多关于 live 事件处理程序的信息。

那就是它了。我正在学习jQuery,这个问题困扰了我几天。感谢您提供清晰、简明的答案。 - Raj
.live()在1.7中已被弃用,即使在使用早期版本的jQuery的项目中,也不建议使用它。 - saluce
@saluce - 说得好,但当我写这个答案时,“live”仍然非常活跃和繁荣。 - Anurag

2
当您使用bindclickbind("click", ...)的快捷方式)连接事件处理程序时,只有已经存在的元素被连接。稍后添加的新元素不会被连接。
您可以使用livedelegate函数,或者使用on函数的委托功能,或在添加它们时单独连接它们:
  • Live example - Using the latest jQuery and delegate (you can also use on, but I like how delegate documents my intent):

    jQuery(function($) {
    
      $("#theButton").click(function() {
        $("#container").append(
          "<div><a class='test' href='#'>X</a></div>"
        );
      });
    
      $("#container").delegate("a.test", "click", function() {
        alert("Clicked");
      });
    
    });
    
  • Live example - Using the latest jQuery and on (note that the order of arguments is different from delegate):

    jQuery(function($) {
    
      $("#theButton").click(function() {
        $("#container").append(
          "<div><a class='test' href='#'>X</a></div>"
        );
      });
    
      $("#container").on("click", "a.test", function() {
        alert("Clicked");
      });
    
    });
    
  • Live example - Using your jQuery vesion (1.3.0?!) and hooking them up as you add them:

    jQuery(function($) {
    
      $("#theButton").click(function() {
        $("<div><a class='test' href='#'>X</a></div>")
          .click(aTestClick)
          .appendTo("#container");
      });
    
      $("a.test").click(aTestClick);
    
      function aTestClick() {
        alert("Clicked");
      }
    
    });
    

离题(略):
  1. jQuery 1.3.0已经过时了九个版本和两年多的时间。当前版本(原回答时,即2011年3月)为1.5.1,即使您想坚持使用1.3版本,也有不止一个而是两个维护版本发布。
  2. 您正在使用两个独立的“ready”调用,首先是显式的一个,然后是一个隐式的(您的$,在其中传递一个函数)。只需要一个。
  3. 强烈建议不要依赖分号插入,它是魔鬼的孩子。以分号结尾以确保脚本可以被压缩/打包,仅仅因为解释器有时会猜错。

感谢提供的示例。实际上,我在我的代码中使用的是最新版本的jQuery,但我在网上找到了一些似乎有点旧的东西,它使用了当时的版本,这就是我基于最小示例的原因。还要感谢您提到的两个ready调用---我正在逐渐熟悉jQuery,并感谢您的指引。我来自Python,那里语义上重要的空格是常态---需要养成用分号结束语句的习惯。再次感谢! - Raj
@Raj:别担心,希望有所帮助!最好的祝福。 - T.J. Crowder
.live()在1.7版本中已被弃用,建议在1.7及以上版本使用.on(),或者在1.7之前使用.delegate() - saluce
@T.J.Crowder 这是一个错误,我没有注意到时间戳,直到太晚才能撤销投票 =/ - saluce

2

您的事件处理程序未添加到后续附加的元素中。有几种方法可以动态地附加事件处理程序。对于较新版本的jQuery(1.7+),请使用带有选择器的.on()函数。

$('.container').on('click', 'a.live', function() { alert("I'm on"); });

旧版本的jQuery没有.on()方法,因此您可以使用.live()。然而,需要注意的是.live()在1.7版本中已被弃用。

$('a.live').live('click', function() { alert("I'm live"); });

即使是jQuery团队也建议使用.live()的替代方法,无论您使用的jQuery版本是什么。对于早于1.7版本的jQuery,请使用.delegate()
$('.container').delegate('a.test', 'click', function() { alert("I'm delegated"); });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接