简体   繁体   English

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

[英]Stop JS-event propagation on table row click

I have the following HTML-table: 我有以下HTML表:

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

When I click on a tr , I trigger a click on the hidden button with JS: 当我点击tr ,我用JS点击隐藏按钮:

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

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

The click event propagates up, and will cause a never ending loop (can be seen here: http://codepen.io/anon/pen/kDxHy ) click事件向上传播,并将导致一个永无止境的循环(可以在这里看到: http//codepen.io/anon/pen/kDxHy

After some searching on SO, it is clear that the solution is to call event.stopPropagation , 在对SO进行一些搜索之后,很明显解决方案是调用event.stopPropagation
like this (can be seen here: http://codepen.io/anon/pen/BnlfA ): 像这样(可以在这里看到: 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');
});

The solution above works. 上面的解决方案有效。 But it feels like a hack, and I don't like it. 但感觉就像一个黑客,我不喜欢它。

Do I have to register a click handler on the on the $button just to call event.stopPropagation ? 我是否必须在$button上注册一个点击处理程序才能调用event.stopPropagation Are there any better way(s) of preventing the click event from bubbeling? 有没有更好的方法来阻止点击事件的冒泡?

A better overall solution would be not to trigger the click event at all but simply have a seperate function that you can call and that encapsulates the event handler logic. 一个更好的整体解决方案是根本不触发click事件,只是简单地有一个你可以调用的单独函数,它封装了事件处理程序逻辑。

function doSomething(someArg) {
    //do something
}

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

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

Please note that doSomething doesn't have an event handler signature such as (e) . 请注意, doSomething没有事件处理程序签名,如(e) That's generally a good practice to pass just what's needed to the function to do it's own work, not the whole event object. 这通常是一种很好的做法,可以将函数所需的内容传递给自己的工作,而不是整个事件对象。 That will simplify the implementation of doSomething and decouple it completely from the event object. 这将简化doSomething的实现并将其与事件对象完全分离。

EDIT: 编辑:

Sorry, but I need to manually trigger the button click when the user clicks on a tr. 抱歉,我需要在用户点击tr时手动触发按钮点击。 Please see my comment to @magyar1984 question. 请参阅我对@ magyar1984问题的评论。

In this case you probably found the best solution already, which is to attach an event listener on the button and call stopPropagation . 在这种情况下,您可能已经找到了最佳解决方案,即在按钮上附加事件监听器并调用stopPropagation You could also look into getting all click event handlers by using the events data on the element, but beware that you would then be relying on jQuery internals so the code could break in future releases. 您还可以通过使用元素上的events数据来查看获取所有单击事件处理程序,但请注意,您将依赖于jQuery内部,因此代码可能会在将来的版本中中断。

Have a look at this question to know how to retrieve the event handlers. 看看这个问题 ,了解如何检索事件处理程序。

I was able to get it to only register the button click once by updating your codepen to the following: 我能够通过将您的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);
});

But the general idea is to declare an onClick event on the button and stop the propagation there. 但一般的想法是在按钮上声明onClick事件并停止传播。

Modifying buttons behaviour, expecially in frameworks, can cause some unexpected issues. 修改按钮行为,特别是在框架中,可能会导致一些意外问题。 You could add a flag to the row and use it to check if the button should be clicked. 您可以向该行添加一个标志,并使用它来检查是否应该单击该按钮。 But you have to know how many click are automatically generated and should be omitted. 但您必须知道自动生成了多少次点击,应该省略。

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;
};

Here's the code: http://codepen.io/anon/pen/dJroL 这是代码: http//codepen.io/anon/pen/dJroL

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM