多次触发 jQuery 单击事件

IT技术 javascript jquery click jquery-events
2021-01-23 06:25:06

我正在尝试用 Javascript 编写一个视频扑克游戏,作为了解它的基础知识的一种方式,但我遇到了一个问题,即 jQuery 单击事件处理程序多次触发。

它们附在用于下注的按钮上,在游戏期间对第一手牌进行下注时效果很好(仅触发一次);但在为第二手牌下注时,每次按下下注或下注按钮时,它都会触发两次 click 事件(因此每次按下时下注正确金额的两倍)。总的来说,当按下下注按钮一次时,点击事件被触发的次数遵循这种模式——序列第 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
        }
    });
}

如果您有任何想法或建议,或者我的问题的解决方案与此处另一个问题的解决方案相似,请告诉我(我查看了许多类似标题的线程,但没有找到可行的解决方案给我)。

6个回答

要确保仅单击一次操作,请使用以下命令:

$(".bet").unbind().click(function() {
    //Stuff
});
男人在做了这么多事情之后做到了。除了在我的情况下,我使用了相当于: $(".bet").off().on()
2021-03-14 06:25:06
;) 对不起。我也在这个轮子上转了几天。我仍然在寻找一个合乎逻辑的理由来解释为什么它首先发生。
2021-03-23 06:25:06
点击处理程序不是一次性的东西。尤其是当问题中显示庞大的 if-if-if 时。您应该附加它并让它在页面存在时发挥作用。
2021-03-24 06:25:06
好的,你昨天在哪里,罗布?;) 这正是我要找的,不知道为什么我之前没有找到。但这仍然是因祸得福,因为我确实学到了很多其他东西。
2021-04-07 06:25:06
正如下面 jroi_web 所说,此方法已被弃用。有关更新的解决方案,请参阅 @trolle 的答案。
2021-04-10 06:25:06

.unbind()已弃用,您应该改用该.off()方法。只需.off()在您致电之前致电.on()

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

$(element).off().on('click', function() {
    // function body
});

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

$(element).off('click').on('click', function() {
    // function body
});
这应该在较新版本的 jQuery 中使用,因为 unbind、die 或 live 已被弃用
2021-03-19 06:25:06
奇迹般有效!我的函数会在单击时运行一次,然后运行两次,四次......在 .on() 之前 .off() 解决了这个问题。
2021-04-09 06:25:06

。一()

更好的选择是.one()

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

$(".bet").one('click',function() {
    //Your function
});

在多个类的情况下,每个类都需要点击一次,

$(".bet").on('click',function() {
    //Your function
    $(this).off('click');   //or $(this).unbind()
});
在尝试了所有答案后,这是唯一适合我的答案。
2021-03-17 06:25:06
需要注意的一件事是,如果您希望该功能仅在每次点击时触发一次,但在后续点击时继续触发,则该功能在页面的整个生命周期内实际上只会触发一次。因此需要使用 mtl 对 off().on() 方法的回答。
2021-03-17 06:25:06
对我不起作用 - 仍然多次点击触发 - 没有意义,因为只有 1 个带有 ID 的按钮元素并且只有 1 个事件被捕获(点击事件)。我认为这是一个 jQuery 错误,但它可能是一个 Bootstrap 模式对话框错误。
2021-03-21 06:25:06
最好的答案,你从一个愚蠢的黑客救了我,这是更好的,因为,如果你有多个onclick事件相同的元素,但在不同的地点,这将不会影响休息,而unbind()off()只会破坏等onclick又在发谢谢
2021-03-28 06:25:06
@munchschair,这可能有多种原因。彼此内部具有相同类的多个元素。或者在迭代中多次注册点击处理程序。
2021-04-03 06:25:06

如果您发现 .off() .unbind() 或 .stopPropagation() 仍然不能解决您的特定问题,请尝试使用.stopImmediatePropagation()在您只想处理事件而没有任何冒泡且没有任何冒泡的情况下效果很好影响已经处理的任何其他事件。就像是:

$(".bet").click(function(event) {
  event.stopImmediatePropagation();
  //Do Stuff
});

行得通!

我去了超过15个答案,终于找到了e.stopImmediatePropagation
2021-03-11 06:25:06
这对我以及阻止事件触发两次都有帮助,但也让我大吃一惊。事实证明,如果您在附加到 jQuery UI 对话框字段的事件处理程序中使用 event.stopImmediatePropagation(),那么由于某种原因,对话框不能再引用全局变量的最新实例,而是使用全局变量的版本在 jQuery UI 对话框渲染之前。这意味着,例如,如果您的全局变量已声明,但在 jQuery UI 对话框呈现时未初始化,则它将显示为未初始化的 jQuery UI 对话框事件处理程序
2021-03-22 06:25:06
对我来说完全没问题。谢谢!
2021-04-02 06:25:06
或者,如果您在呈现 jQuery UI Dialog 之前为某个全局变量分配了 16 的值,该值后来更改为 55,那么 16 将在 jQuery UI Dialog 事件处理程序中显示该全局变量,即使当时是不再是 16。因此,它看起来像是人们应该注意的 jQuery UI 错误。
2021-04-06 06:25:06
对于甚至难以描述的非常具体的情况。它的工作原理与您所说的完全一样:“工作而不影响任何其他事件”。谢谢!:)
2021-04-09 06:25:06

如果您在每次“点击”时调用该函数,那么它会在每次调用时添加另一对处理程序。

使用 jQuery 添加处理程序与设置“onclick”属性的值不同。可以根据需要添加任意数量的处理程序。

您的回答使我朝着正确的方向前进,我学到了很多东西,但不幸的是,还不足以解决我使用 jQuery 的问题。:) 我尝试使用 on/off、live(和委托)/die 和一个,然后 addEventListener/removeEventListener,但我能做的最好的事情是减缓处理程序的指数增长。我最终暂时用 onclick 解决了我的问题。但是我仍然从你的回答中学到了很多关于 Javascript 事件模型的知识,比如捕获/冒泡,所以我很感激。谢谢你。:)
2021-04-04 06:25:06
非常感谢,我不敢相信我不知道这个!
2021-04-08 06:25:06