在表行单击上停止JS事件传播

时间:2013-09-23 21:03:39

标签: javascript javascript-events jquery

我有以下HTML表:

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

当我点击tr时,我触发了点击隐藏按钮的JS:

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

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

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?有没有更好的方法来阻止点击事件的冒泡?

3 个答案:

答案 0 :(得分:0)

更好的整体解决方案根本不是触发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内部,因此代码可能会在将来的版本中中断。

请查看this question以了解如何检索事件处理程序。

答案 1 :(得分:0)

我能够通过将您的codepen更新为以下内容来仅注册按钮一次:

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事件并停止传播。

答案 2 :(得分: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

相关问题