尝试更改父级的jQuery单击处理程序会触发新的单击事件

时间:2015-07-18 23:06:00

标签: javascript jquery events

我在使用jQuery的事件监听器中遇到了一些(对我而言)意外行为,但我希望它只是让我感到困惑的底层Javascript功能。我认为我的问题答案很简单,但我无法弄清楚。

我有一个<div>,其中包含一个状态,即&#39;新&#39;默认情况下。我希望能够点击<div>并打开一对按钮,其中一个按钮可以让您更换“新的”按钮。状态文字带有&#39;完成&#39;,另一个将取消操作,删除按钮并显示&#39;新&#39;状态文本。

我可以让一切工作,如果我使用不同的元素来显示按钮,一切正常,但是当我尝试暂时替换<div>中的文本时,会发生一些奇怪的事情。

当我尝试重置<div>的原始点击事件时,似乎发生的情况是点击取消按钮也会触发刚刚设置的点击事件。这会重新显示按钮,因此取消按钮看起来不起作用。 (我被困了一段时间......)

我做了一个非常简单的JSFiddle,它显示了我遇到的问题:

https://jsfiddle.net/pn1q658w/4/

还有一个稍微修改过的版本,只要我在取消按钮的位置与我重置原始点击功能的元素不同,就会显示工作正常:< / p>

https://jsfiddle.net/pn1q658w/3/

我认为这与我不完全理解这些事件发生时间的方式有关。同样的点击似乎触发了一个事件,该事件是在由于该点击而采取的动作期间设置的,我没有预料到,但很可能是事情应该如何工作。

我的问题是如何让点击事件尝试在父元素上设置点击侦听器,而不是同时触发新点击?

或者,如果我完全误解了我的错误的性质,我将非常感谢你做错了什么。谢谢!

4 个答案:

答案 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()然后再次添加相同的处理程序。