Estoy tratando de escribir un juego de video póker en Javascript como una forma de obtener los conceptos básicos, y me he encontrado con un problema en el que los controladores de eventos jQuery click se disparan varias veces.
Están unidos a botones para hacer una apuesta, y funciona bien para hacer una apuesta en la primera mano durante un juego (disparando solo una vez); pero al apostar por la segunda mano, dispara el evento de clic dos veces cada vez que se presiona un botón de apuesta o apuesta de lugar (por lo que se apuesta dos veces la cantidad correcta por cada presión). En general, sigue este patrón por la cantidad de veces que se dispara el evento de clic cuando se presiona un botón de apuesta una vez, donde el i-ésimo término de la secuencia es para apostar 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 sea que valga la pena, y no era lo suficientemente inteligente como para entender eso, usé OEIS . :)
Aquí está la función con los controladores de eventos de clic que están actuando; espero que sea fácil de entender (avíseme si no, también quiero mejorar en eso):
/** 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 examinado muchos hilos con títulos similares y no tuve suerte en encontrar una solución que pudiera funcionar para mi).
fuente
var amount = parseInt(this.id.replace(/[^\d]/g,''),10);
Y si va a usar la misma propiedad de un elemento más de una vez, almacene esa propiedad, no siga buscando. La búsqueda es costosa.Respuestas:
Para asegurarse de que solo haga clic en acciones una vez use esto:
fuente
.unbind()
está en desuso y debería usar el.off()
método en su lugar. Simplemente llame.off()
justo antes de llamar.on()
.Esto eliminará todos los controladores de eventos:
Para eliminar solo los controladores de eventos 'clic' registrados:
fuente
.uno()
Una mejor opción sería
.one()
:En el caso de varias clases y cada clase debe hacerse clic una vez,
fuente
onclick
eventos al mismo elemento, pero en diferentes lugares esto no va a afectar el resto, mientras queunbind()
yoff()
sólo va a destruir otrosonclick
s gracias de nuevoSi 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 efectuando cualquier otro evento que ya se esté manejando. Algo como:
¡Hace el truco!
fuente
Si llama a esa función en cada "clic", entonces está agregando otro par de controladores en cada llamada.
Agregar controladores con jQuery simplemente no es como establecer el valor del atributo "onclick". Se pueden agregar tantos controladores como se desee.
fuente
Un evento se disparará varias veces cuando se registre varias veces (incluso si se trata del mismo controlador).
por ejemplo,
$("ctrl").on('click', somefunction)
si este código se ejecuta cada vez que la página se actualiza parcialmente, el evento también se registra cada vez. Por lo tanto, incluso si se hace clic en ctrl solo una vez, puede ejecutar "alguna función" varias veces; cuántas veces se ejecute dependerá de cuántas veces se haya registrado.Esto es cierto para cualquier evento registrado en JavaScript.
solución:
asegúrese de llamar "encendido" solo una vez.
y por alguna razón si no puede controlar la arquitectura, haga esto:
$("ctrl").off('click'); $("ctrl").on('click', somefunction);
fuente
Tuve un problema debido al marcado.
HTML:
jQuery
Te das cuenta de que tengo la misma clase 'myclass' dos veces en html, por lo que llama click para cada instancia de div.
fuente
La mejor opción sería usar off
fuente
Todo lo relacionado con .on () y .one () es excelente, y jquery es excelente.
Pero a veces, desea que sea un poco más obvio que el usuario no puede hacer clic, y en esos casos puede hacer algo como esto:
y tu botón se vería así:
fuente
Ocurre debido a que el evento particular está vinculado varias veces al mismo elemento.
La solución que funcionó para mí es:
Mata todos los eventos adjuntos usando el
.die()
método.Y luego adjunte su método de escucha.
Así,
debiera ser:
fuente
Debemos hacerlo
stopPropagation()
Para evitar clics desencadena el evento demasiadas veces.Impide que el evento forme burbujas en el árbol DOM, evitando que cualquier controlador principal sea notificado del evento. Este método no acepta ningún argumento.
Podemos usar
event.isPropagationStopped()
para determinar si este método fue llamado alguna vez (en ese objeto de evento).Este método también funciona para eventos personalizados activados con trigger (). Tenga en cuenta que esto no impedirá que se ejecuten otros controladores en el mismo elemento.
fuente
En mi caso, estaba usando 'delegado', por lo que ninguna de estas soluciones funcionó. Creo que fue el botón que apareció varias veces a través de llamadas ajax lo que estaba causando el problema de clics múltiples. Las soluciones estaban usando un tiempo de espera, por lo que solo se reconoce el último clic:
fuente
Documentos:
http://api.jquery.com/one/
fuente
fuente
.one solo se dispara una vez durante toda la vida de la página
Entonces, en caso de que desee hacer la validación, esta no es la solución correcta, porque cuando no abandona la página después de la validación, nunca regresa. Mejor usar
fuente
Cuando trato con este problema, siempre uso:
De esta manera, me desengancho y vuelvo a unir de la misma manera.
fuente
https://jsfiddle.net/0vgchj9n/1/
Para asegurarse de que el evento siempre se active solo una vez, puede usar Jquery .one (). JQuery one asegura que su controlador de eventos solo llame una vez. Además, puede suscribir su controlador de eventos con uno para permitir más clics cuando haya finalizado el procesamiento de la operación de clics actual.
...
fuente
Intenta de esa manera:
fuente
En mi caso, el evento onclick se disparó varias veces porque había hecho un controlador de eventos genérico comparativamente como
cambiado a
y también tienen que hacer manejadores separados para clics estáticos y dinámicos, para clics en pestañas estáticas
fuente
En mi caso, había cargado el mismo
*.js
archivo en la página dos veces en una<script>
etiqueta, por lo que ambos archivos adjuntaron controladores de eventos al elemento. Eliminé la declaración duplicada y eso solucionó el problema.fuente
Otra solución que encontré fue esta, si tienes varias clases y estás lidiando con botones de radio mientras haces clic en la etiqueta.
fuente
Estaba teniendo este problema con un enlace generado dinámicamente:
$(document).on('click', '#mylink', function({...do stuff...});
Encontré reemplazar
document
con'body'
solucionado el problema para mí:$('body').on('click', '#mylink', function({...do stuff...});
fuente
Unbind () funciona, pero eso puede causar otros problemas en el futuro. El controlador se dispara varias veces cuando está dentro de otro controlador, por lo tanto, mantenga su controlador fuera y, si desea los valores del controlador que se anidó, asígnelos a una variable global que sea accesible para su controlador.
fuente
En caso de que esto funcione bien
fuente
El código siguiente funcionó para mí en mi aplicación de chat para manejar múltiples eventos de activación del clic del mouse más de una vez.
if (!e.originalEvent.detail || e.originalEvent.detail == 1) { // Your code logic }
fuente