Los eventos de clic de jQuery se activan varias veces

Resuelto Gregory Fowler asked hace 11 años • 29 respuestas

Estoy intentando escribir un juego de video póquer en Javascript como una forma de comprender los conceptos básicos y me encontré con un problema en el que los controladores de eventos de clic de jQuery se activan varias veces.

Están adjuntos a botones para realizar una apuesta y funcionan bien para realizar una apuesta en la primera mano durante un juego (disparándose solo una vez); pero al apostar para la segunda mano, activa el evento de clic dos veces cada vez que se presiona un botón de apuesta o de realizar apuesta (por lo que se apuesta el doble de la cantidad correcta por cada presión). En general, sigue este patrón para la cantidad de veces que se activa el evento de clic al presionar un botón de apuesta una vez, donde el i-ésimo término de la secuencia es para la apuesta de la i-ésima mano desde el comienzo del juego: 1, 2, 4 , 7, 11, 16, 22, 29, 37, 46, que parece ser n(n+1)/2 + 1 para lo que valga la pena, y no fui lo suficientemente inteligente como para darme cuenta de eso, usé OEIS . :)

Aquí está la función con los controladores de eventos de clic que están funcionando mal; Espero que sea fácil de entender (avíseme si no, quiero mejorar en eso también):

/** 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
        }
    });
}

Avíseme si tiene alguna idea o sugerencia, o si la solución a mi problema es similar a una solución a otro problema aquí (he mirado muchos hilos con títulos similares y no tuve suerte en encontrar una solución que pudiera funcionar). para mí).

Gregory Fowler avatar Feb 20 '13 07:02 Gregory Fowler
Aceptado

Para asegurarse de que un clic solo actúe una vez, use esto:

$(".bet").unbind().click(function() {
    //Stuff
});
Rob avatar Feb 20 '2013 22:02 Rob

.unbind()está en desuso y deberías utilizar el .off()método en su lugar. Simplemente llame .off()justo antes de llamar .on().

Esto eliminará todos los controladores de eventos:

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

Para eliminar únicamente los controladores de eventos de "clic" registrados:

$(element).off('click').on('click', function() {
    // function body
});
mtl avatar Jan 02 '2014 10:01 mtl

.uno()

Una mejor opción sería .one():

El controlador se ejecuta como máximo una vez por elemento y por tipo de evento.

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

En caso de que haya varias clases y sea necesario hacer clic en cada clase una vez,

$(".bet").on('click',function() {
    //Your function
    $(this).off('click');   //or $(this).unbind()
});
Shaunak D avatar Jun 14 '2014 09:06 Shaunak D

Si encuentra que .off() .unbind() o .stopPropagation() aún no soluciona su problema específico, intente usar .stopImmediatePropagation() Funciona muy bien en situaciones en las que solo desea que su evento se maneje sin burbujas y sin efectuar cualquier otro evento que ya se esté manejando. Algo como:

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

¡Hace el truco!

Alfonse Pinto avatar Mar 19 '2015 18:03 Alfonse Pinto