jQuery单击事件多次触发

Gre*_*ler 265 javascript jquery click jquery-events

我试图用Javascript编写一个视频扑克游戏作为一种获取它的基础知识的方法,并且我遇到了jQuery点击事件处理程序多次触发的问题.

它们附在用于下注的按钮上,并且它适用于在比赛期间在第一手牌上下注(仅发射一次); 但是在投注秒针时,每次按下下注或下注按钮时,它都会触发点击事件两次(因此每次按下两次正确的金额).总的来说,它遵循这种模式,按下一次下注按钮时点击事件被触发的次数 - 其中序列的第i个术语是从游戏开始时第i个手的投注:1,2,4 ,7,11,16,22,29,37,46,对于任何值得的东西来说似乎是n(n + 1)/ 2 + 1 - 而且我还不够聪明,我用过OEIS.:)

这是使用单击事件处理程序的函数; 希望它很容易理解(如果没有,请告诉我,我也希望在这方面做得更好):

/** The following function keeps track of bet buttons that are pressed, until place button is pressed to place bet. **/
function pushingBetButtons() {
    $("#money").text("Money left: $" + player.money); // displays money player has left

    $(".bet").click(function() {
        var amount = 0; // holds the amount of money the player bet on this click
        if($(this).attr("id") == "bet1") { // the player just bet $1
            amount = 1;
        } else if($(this).attr("id") == "bet5") { // etc.
            amount = 5;
        } else if($(this).attr("id") == "bet25") {
            amount = 25;
        } else if($(this).attr("id") == "bet100") {
            amount = 100;
        } else if($(this).attr("id") == "bet500") {
            amount = 500;
        } else if($(this).attr("id") == "bet1000") {
            amount = 1000;
        }
        if(player.money >= amount) { // check whether the player has this much to bet
            player.bet += amount; // add what was just bet by clicking that button to the total bet on this hand
            player.money -= amount; // and, of course, subtract it from player's current pot
            $("#money").text("Money left: $" + player.money); // then redisplay what the player has left
        } else {
            alert("You don't have $" + amount + " to bet.");
        }
    });

    $("#place").click(function() {
        if(player.bet == 0) { // player didn't bet anything on this hand
            alert("Please place a bet first.");
        } else {
            $("#card_para").css("display", "block"); // now show the cards
            $(".card").bind("click", cardClicked); // and set up the event handler for the cards
            $("#bet_buttons_para").css("display", "none"); // hide the bet buttons and place bet button
            $("#redraw").css("display", "block"); // and reshow the button for redrawing the hand
            player.bet = 0; // reset the bet for betting on the next hand
            drawNewHand(); // draw the cards
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

如果您有任何想法或建议,或者我的问题的解决方案与此处的另一个问题的解决方案类似,请告诉我(我已经查看了许多类似标题的线程,并且没有找到可以工作的解决方案的运气为了我).

Rob*_*Rob 494

要确保只使用一次点击操作,请执行以下操作:

$(".bet").unbind().click(function() {
    //Stuff
});
Run Code Online (Sandbox Code Playgroud)

  • 好的,你昨天在哪里,罗布?;)这正是我正在寻找的,不知道为什么我以前没有找到它.但它仍然是一种伪装的祝福,因为我确实学到了很多其他的东西. (31认同)
  • 正如jroi_web在下面所说,这种方法已被弃用.有关更新的解决方案,请参阅@ trolle的答案. (6认同)
  • 经过这么多事情的人就这样做了.除了在我的情况下,我使用相当于:$(".bet").off().on() (5认同)
  • ;) 对不起。我也在这件事上转了几天。我仍在寻找一个逻辑原因来解释为什么它会首先发生。 (2认同)
  • 点击处理程序不是一次性的东西。尤其是当问题中显示出大量的 if-if-if 时。您应该附加它并让它在页面存在期间完成其工作。 (2认同)

mtl*_*mtl 362

.unbind()已弃用,您应该使用该.off()方法.在打电话.off()之前,只需打电话.on().

这将删除所有事件处理程序:

$(element).off().on('click', function() {
    // function body
});
Run Code Online (Sandbox Code Playgroud)

要仅删除已注册的"点击"事件处理程序:

$(element).off('click').on('click', function() {
    // function body
});
Run Code Online (Sandbox Code Playgroud)

  • .off()似乎需要参数才能删除特定元素的特定处理程序,否则所有事件处理程序似乎都会被删除.例如`('body').off("click",element).on('click',element,function(){//代码继续`.我不确定这是不是因为我使用`$(body )`然后是元素但是对于这种情况,`off()`似乎需要params来专门针对手头的元素. (10认同)
  • 这应该在较新版本的jQuery中使用,因为unbind,die或live已被弃用 (9认同)

Sha*_*k D 138

.一()

更好的选择是.one():

每个事件类型的每个元素最多执行一次处理程序.

$(".bet").one('click',function() {
    //Your function
});
Run Code Online (Sandbox Code Playgroud)

如果有多个类,每个类需要单击一次,

$(".bet").on('click',function() {
    //Your function
    $(this).off('click');   //or $(this).unbind()
});
Run Code Online (Sandbox Code Playgroud)

  • 最好的答案,你救了我一个愚蠢的黑客,这是更好的因为它如果你有多个`onclick`事件到同一个元素但在不同的位置这不会影响其余的,而`unbind()`和`关闭( )``只会破坏其他`onclick'再次谢谢你 (8认同)
  • 有一点需要注意的是,如果你想让这个功能只触发一次PER CLICK,但是继续点击后续点击,这个只会在页面的生命周期中触发一次.因此需要使用mtl使用off().on()方法的答案. (8认同)
  • 在尝试了所有答案后,这一个是唯一适合我的人. (3认同)
  • @munchschair,这可能有多种原因。彼此内部具有相同类的多个元素。或者在一次迭代中多次注册单击处理程序。 (2认同)
  • 不适合我 - 仍然是多次点击 - 没有任何意义,因为只有一个带ID的按钮元素,只有一个事件被捕获(点击事件).我认为这是一个jQuery错误,但它可能是一个Bootstrap模式对话框错误. (2认同)

Alf*_*nto 73

如果您发现.off().unbind()或.stopPropagation()仍然无法解决您的具体问题,请尝试使用.stopImmediatePropagation()在您只希望处理事件时不需要任何冒泡且没有任何冒泡的情况下工作得很好影响已经处理的任何其他事件.就像是:

$(".bet").click(function(event) {
  event.stopImmediatePropagation();
  //Do Stuff
});
Run Code Online (Sandbox Code Playgroud)

诀窍!

  • 或者,如果您在呈现 jQuery UI Dialog 之前为某个全局变量分配了 16 的值,该值后来更改为 55,那么 16 将在 jQuery UI Dialog 事件处理程序中显示该全局变量,即使当时是不再是 16。因此,它看起来像是人们应该注意的 jQuery UI 错误。 (2认同)
  • 我找了超过15个答案,终于找到了这个`e.stopImmediatePropagation`! (2认同)

Poi*_*nty 17

如果你在每次"点击"时调用该函数,那么它会在每次调用时添加另一对处理程序.

使用jQuery添加处理程序与设置"onclick"属性的值不同.可以根据需要添加尽可能多的处理程序.

  • 你的答案让我朝着正确的方向前进,我学到了很多东西,但不足以使用jQuery来解决我的问题.:)我尝试使用on/off,live(和delegate)/ die,然后使用addEventListener/removeEventListener,但我能做的最好的事情是减缓处理程序的指数增长.我最终刚刚用onclick解决了我的问题.但我仍然从你的答案中学到很多关于Javascript的事件模型,比如捕获/冒泡,所以我很感激.谢谢.:) (3认同)
  • 好的,好好学习的东西就是这个网站的全部内容! (2认同)

Kal*_*pat 7

这是一个老问题,但我今天面对它,我认为我的答案将有助于未来寻求类似挑战的人.

它被执行多次,因为"on('click',somefunction)"函数被多次调用,因此它被多次绑定 - 为了永久解决这个问题,你需要确保"on"函数是这样的它只会被执行一次.在鼠标单击事件之后,该函数将仅被触发一次.

例如,如果我将"on('click',somefunction)"放在将被加载两次的地方,那么每次点击 - "somefunction"将被触发两次.

在正确的逻辑序列中,只有在您真正打算取消绑定事件时才应使用"off"函数.使用它来隐藏由于"on"函数的双重加载而导致的逻辑错误,即使它似乎工作也不是一个好方法.

  • 我们不知道函数"pushBetButtons"是仅被调用一次还是多次..如果它被调用多次,则事件被多次注册,因此它也将触发多次...即使按钮被单击一次也是如此. (2认同)

小智 6

我们必须stopPropagation()为了避免Clicks触发事件太多次。

$(this).find('#cameraImageView').on('click', function(evt) {
   evt.stopPropagation();
   console.log("Camera click event.");
});
Run Code Online (Sandbox Code Playgroud)

它防止事件在 DOM 树中冒泡,从而防止任何父处理程序收到该事件的通知。此方法不接受任何参数。

我们可以用来event.isPropagationStopped()确定是否曾经调用过此方法(在该事件对象上)。

此方法也适用于使用trigger() 触发的自定义事件。请注意,这不会阻止同一元素上的其他处理程序运行。