我在使用jQuery的事件监听器中遇到了一些(对我而言)意外行为,但我希望它只是让我感到困惑的底层Javascript功能。我认为我的问题答案很简单,但我无法弄清楚。
我有一个<div>
,其中包含一个状态,即&#39;新&#39;默认情况下。我希望能够点击<div>
并打开一对按钮,其中一个按钮可以让您更换“新的”按钮。状态文字带有&#39;完成&#39;,另一个将取消操作,删除按钮并显示&#39;新&#39;状态文本。
我可以让一切工作,如果我使用不同的元素来显示按钮,一切正常,但是当我尝试暂时替换<div>
中的文本时,会发生一些奇怪的事情。
当我尝试重置<div>
的原始点击事件时,似乎发生的情况是点击取消按钮也会触发刚刚设置的点击事件。这会重新显示按钮,因此取消按钮看起来不起作用。 (我被困了一段时间......)
我做了一个非常简单的JSFiddle,它显示了我遇到的问题:
https://jsfiddle.net/pn1q658w/4/
还有一个稍微修改过的版本,只要我在取消按钮的位置与我重置原始点击功能的元素不同,就会显示工作正常:< / p>
https://jsfiddle.net/pn1q658w/3/
我认为这与我不完全理解这些事件发生时间的方式有关。同样的点击似乎触发了一个事件,该事件是在由于该点击而采取的动作期间设置的,我没有预料到,但很可能是事情应该如何工作。
我的问题是如何让点击事件尝试在父元素上设置点击侦听器,而不是同时触发新点击?
或者,如果我完全误解了我的错误的性质,我将非常感谢你做错了什么。谢谢!
答案 0 :(得分:1)
<强>已更新强>
就像@charlietfl说的那样,我嗤之以鼻,最简单的方法就是用自己的班级来分析每个人,参见 WORKED FIDDLE HERE :
HTML:
<div id="elementId">
<span class='text'>New</span>
</div>
JS:
$(function(){
var newBtn = '<button class="btn btn-default complete">Complete?</button><button class="btn btn-default cancel">X</button>';
//Handle the click in the text span
$("#elementId").on("click","span.text",function(e){
$(this).html(newBtn);
});
//Handle the click in the complete button
$("#elementId").on("click","button.complete",function(e){
$('#elementId').html("<span class='text'>Completed</span>");
});
//Handle the click in the cancel button
$("#elementId").on("click","button.cancel",function(e){
$('#elementId').html("<span class='text'>New</span>");
});
});
我希望这段代码可以帮助你。
答案 1 :(得分:0)
需要了解的是,当您点击另一个元素中的元素时......您仍然会点击父元素。
事件“冒泡”或“传播”DOM树一直到文档...除非告诉stopPropagation()
您所看到的是预期的行为。
您可以通过以下方式阻止冒泡:
$(selector).click(function(event){
event.stopPropagation();
});
您的代码中有一些奇怪的东西可以简化地简化 首先将元素传递给处理程序...然后获取该元素的属性以创建一个选择器,以便在DOM中再次找到完全相同的元素
var cellId = element.id;
$('#' + cellId)
可以简化为
$(element);// doesn't require searching for the ID
也可以存储为变量,而不是一遍又一遍地使用相同的选择器
var $el = $(element);
$el.off('click');
var oldCellContent = $el.text();
这些简化更有效,更易于阅读
答案 2 :(得分:0)
问题是你重写了div的alaways内容,因为你没有停止传播。
我用这段代码解决了你的问题:
var oldCellContent = $('#elementId').text();
var newButtons = '<button class="btn btn-default complete">Complete?</button><button class="btn btn-default delete">X</button>';
$("#elementId").click(function(){
$(this).html(newButtons);
});
$("#elementId").on("click","button.complete",function(e){
console.log('The complete function fired.');
$('#elementId').text('Completed');
e.stopPropagation();
});
$("#elementId").on("click","button.delete",function(e){
console.log('The cancel function fired.');
$('#elementId').text(oldCellContent);
e.stopPropagation();
});
答案 3 :(得分:0)
所有这一切的最简单的解决方案是将“新”文本包装在它自己的元素中,并在该元素上放置“show buttons”click handler并同时隐藏“new”。
代码将更简单,不会有任何传播问题或需要使用off()然后再次添加相同的处理程序。