4

我有以下 HTML 表:

<table>
  <tr>
    <td>
      Row 1
    </td>
    <td>
      <!-- Hidden JSF-button -->
      <button class="hide" />
    </td>
  </tr>
</table>

当我点击 atr时,我触发了对带有 JS 的隐藏按钮的点击:

$('table tr').on('click', function(e) {
  var $button = $(this).find('button');  
  console.log('trigger click on', $button);

  $button.trigger('click');
});

点击事件向上传播,并将导致一个永无止境的循环(可以在这里看到: http: //codepen.io/anon/pen/kDxHy

在 SO 上进行一些搜索后,很明显解决方案是调用event.stopPropagation
就像这样(可以在这里看到: http: //codepen.io/anon/pen/BnlfA):

$('table tr').on('click', function(e) {
  var $button = $(this).find('button');

  // Prevent the event from bubbling up the DOM tree.
  $button
    .off('click')
    .on('click', function(e) {
      console.log('click');
      e.stopPropagation();

    return true;
  });

  console.log('trigger click on', $button);

  $button.trigger('click');
});

上面的解决方案有效。但这感觉就像一个黑客,我不喜欢它。

我是否必须在$button刚刚调用的时候注册一个点击处理程序event.stopPropagation?有没有更好的方法来防止点击事件冒泡?

4

3 回答 3

1

一个更好的整体解决方案是根本不触发click事件,而只是拥有一个可以调用并封装事件处理程序逻辑的单独函数。

function doSomething(someArg) {
    //do something
}

$('button').click(function () {
    doSomething(/*pass whatever you want*/);
});

$('table tr').on('click', function () {
    doSomething(/*pass whatever you want*/);
});

请注意,doSomething它没有事件处理程序签名,例如(e). 这通常是一个很好的做法,只将所需的内容传递给函数来完成它自己的工作,而不是整个事件对象。这将简化实现doSomething并将其与事件对象完全分离。

编辑:

抱歉,但是当用户单击 tr 时,我需要手动触发按钮单击。请参阅我对@magyar1984 问题的评论。

在这种情况下,您可能已经找到了最好的解决方案,即在按钮上附加一个事件侦听器并调用stopPropagation. 您还可以考虑通过使用元素上的数据来获取所有单击事件处理程序events,但请注意,您将依赖 jQuery 内部,因此代码可能会在将来的版本中中断。

查看此问题以了解如何检索事件处理程序。

于 2013-09-23T21:19:01.507 回答
0

修改按钮行为,特别是在框架中,可能会导致一些意想不到的问题。您可以向该行添加一个标志并使用它来检查是否应单击该按钮。但是你必须知道有多少点击是自动生成的,应该省略。

var handleClick = function(e) {
  var $button = $(this).find('button');  
  console.log('triggerring click on...', $button);
  if (this.clicked !== true) {
    console.log('and clicked!')
    this.clicked = true;
    $button.trigger('click');
  } else
    this.clicked = false;
};

这是代码:http ://codepen.io/anon/pen/dJroL

于 2013-09-25T15:08:12.510 回答
0

通过将您的代码笔更新为以下内容,我能够让它只注册一次按钮单击:

var handleClick = function(e) {
  var $button = $(this).find('button');  
  console.log('trigger click on', $button);

  $button.trigger('click');
};
$('button.hide').on('click',function(e){
  e.stopPropagation();
});

$(function() {
    $('table tr')
    .on('click', handleClick);
});

但总体思路是在按钮上声明一个 onClick 事件并在那里停止传播。

于 2013-09-23T22:09:50.543 回答