我有以下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
?有没有更好的方法来阻止点击事件的冒泡?
答案 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;
};