jQuery点击事件触发多次 :(

4
我有以下情况:
我有一个表格,其中的每个tr都有一个“复制”链接。当用户点击“复制”链接时,父级tr会被克隆并附加到表格中。现在的问题是,第一次单击事件可以正常触发,但第二次单击事件会触发两次,第三次单击事件会触发三次,以此类推。并且,由于我已经“克隆”了tr,我想将单击函数绑定到此克隆的tr的“复制”链接上,有什么解决方案吗?
我尝试过$('.copy-row-link').unbind('click').click(function() { /* the code */ });。
我已经阅读了类似的问题,但它们似乎不能解决我的问题。
我的代码:
$(".copy-row-link").unbind('click').bind('click', function(e)
{
    var strdata = 'class="viewtext" style="background-color:#FFFFFF;" id="highlight1733" onMouseOver="highlight(\'1733\');" onMouseOut="removehighlight(\'1733\');'
    //var newTr = currTr.clone(true).addClass("viewtext").css( { "backgroundColor" : "#FFFFFF" } ).attr(;

    var id = currTr.attr("id"); // currTr is set previously
    var newId = id.replace("highlight", "");
    //alert( newId );
    newId = parseInt( newId );
    newId += 1;     
    var newTr = currTr.clone()
                    .addClass("viewtext newAddedRow")
                    .css("backgroundColor", "#FFFFFF")
                    .attr('id', "highlight" + newId.toString() )
                    .mouseover(
                        function() {                                
                            highlight( newId );
                        }
                    )
                    .mouseout(
                        function() {                                
                            removehighlight( newId );
                        }
                    );

    //newTr.appendTo( currTb );
    newTr.hide();
    newTr.insertAfter( "#" + id );
    newTr.fadeIn(100);
    newTr.attr('id', newId);
    //e.stopPropagation();
    //e.preventDefault();
    //e.stopImmediatePropagation();
    bindToTr(); // Bind to Tr calls this function again
    return false;
});
2个回答

1

你说过

我有一个表格,其中所有的 tr 都有一个“复制”链接

...但是你的代码却使用了

$("#menu-item-copyRow")...

...获取复制链接。一个文档内的ID不能重复, 它们必须完全唯一。

这是jQuery新delegate功能非常方便的地方(但是我们可以在早期版本中轻松模拟它;下面详细介绍)。这是使用delegate的独立示例(live copy);我没有尝试复制您的代码,因为我想避免使事情变得过于复杂,但是应该很容易将此技术应用到您的代码中:

HTML:

<table id='theTable'>
  <tbody>
    <tr>
      <td><a href='#' class='copyrow'>Copy</a></td>
      <td class='descr'>This is a row in the markup</td>
    </tr>
  </tbody>
</table>

JavaScript:

jQuery(function($) {
  var counter = 0;

  $('#theTable').delegate('a.copyrow', 'click', copyRowClick);

  function copyRowClick() {
    var $this, $tr, $clone, $desc, label, n;

    ++counter;
    $this = $(this);
    $tr = $this.parents("tr");
    $clone = $tr.clone();
    $descr = $clone.find('td.descr');
    label = $descr.text();
    n = label.indexOf(" of ");
    if (n >= 0) {
      label = label.substring(0, n);
    }
    label = "Clone #" + counter + " of " + label;
    $descr.text(label);
        $clone.insertAfter($tr);
    return false;
  }

});​

(忽略label的内容,这只是为了让我们知道哪些是复制的。)

因为被复制的元素上没有处理程序,所以我们不必担心附加/分离这些处理程序。上面唯一的事件处理程序在table元素上。

delegate是jQuery 1.4.2+的功能,但是在早期版本中,您可以通过钩住table上的click事件,然后查看event.target属性来看实际点击了什么来轻松模拟它。这是如何做到的(live copy):

jQuery(function($) {
  var counter = 0;

  $('#theTable').click(copyRowClick);

  function copyRowClick(event) {
    var $link, $tr, $clone, $desc, label, n;

    // Is the target an a.copyrow?
    $link = $(event.target);
    if ($link.is('a.copyrow')) {
      // Yes, handle this click -- other than changing the varname
      // $this to $link, the below is identical to the `delegate`
      // handler's version.
      ++counter;
      $tr = $link.parents("tr");
      $clone = $tr.clone();
      $descr = $clone.find('td.descr');
      label = $descr.text();
      n = label.indexOf(" of ");
      if (n >= 0) {
        label = label.substring(0, n);
      }
      label = "Clone #" + counter + " of " + label;
      $descr.text(label);
      $clone.insertAfter($tr);
      return false;
    }
  }

});​

我知道我在发布代码时犯了一个错误,我正在通过类名选择代码。 - Shaheer
@user:好的,我已经更新了几个示例实现,通过事件委托在单击时复制行。通常对于动态结构而言,这比挂钩单个元素更好的选择。祝你好运。 - T.J. Crowder

1

由于代码不清晰,我假设上述函数在所有行/TR中都可以找到? 以下是我的评论: 1-不要多次使用相同的ID,改用class: 2-使用live方法,这样所有“新”行都将具有相同的单击事件:

$(".menu-item-copyRow").live('click', function(e) {
// Code goes here
});

3- 你是通过将当前点击的ID递增来设置新的ID吗?!

var id = currTr.attr("id"); // currTr is set previously
var newId = id.replace("highlight", "");
newId = parseInt( newId );
newId += 1;

你应该计算所有的TR,这样你就可以得到新的ID,类似于这样:
var newID = $('tr','#myTable').length + 1;

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