Estou tentando escrever um jogo de vídeo pôquer em Javascript como uma maneira de obter o básico, e encontrei um problema em que os manipuladores de eventos do jQuery click estão disparando várias vezes.
Eles estão anexados aos botões para fazer uma aposta e funciona bem para fazer uma aposta na primeira mão durante um jogo (disparando apenas uma vez); mas, ao apostar pela segunda mão, ele dispara o evento click duas vezes cada vez que um botão de aposta ou de aposta é pressionado (portanto, o dobro do valor correto é apostado para cada pressionamento). No geral, segue esse padrão pelo número de vezes que o evento click é acionado ao pressionar um botão de aposta uma vez - onde o i - ésimo termo da sequência é para as apostas da i- mão desde o início do jogo: 1, 2, 4 , 7, 11, 16, 22, 29, 37, 46, que parece ser n (n + 1) / 2 + 1 para o que vale a pena - e eu não era inteligente o suficiente para descobrir isso, usei o OEIS . :)
Aqui está a função com os manipuladores de eventos click que estão agindo; espero que seja fácil de entender (deixe-me saber se não, eu também quero melhorar):
/** 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
}
});
}
Informe-me se você tem alguma idéia ou sugestão, ou se a solução para o meu problema é semelhante a uma solução para outro problema aqui (observei muitos tópicos com o mesmo título e não tive sorte em encontrar uma solução que pudesse funcionar) para mim).
fonte
var amount = parseInt(this.id.replace(/[^\d]/g,''),10);
E se você usar a mesma propriedade de um elemento mais de uma vez, armazene em cache essa propriedade, não continue pesquisando. A consulta é cara.Respostas:
Para garantir que um clique apenas as ações sejam usadas uma vez:
fonte
.unbind()
foi descontinuado e você deve usar o.off()
método Basta ligar.off()
antes de ligar.on()
.Isso removerá todos os manipuladores de eventos:
Para remover apenas os manipuladores de eventos registrados 'clique':
fonte
.1()
Uma opção melhor seria
.one()
:No caso de várias classes e cada classe precisa ser clicada uma vez,
fonte
onclick
eventos para o mesmo elemento, mas em locais diferentes, isso não afetará o resto,unbind()
eoff()
destruirá outros,onclick
obrigado novamenteSe você achar que .off () .unbind () ou .stopPropagation () ainda não solucionou seu problema específico, tente usar .stopImmediatePropagation () Funciona muito bem em situações em que você deseja que seu evento seja tratado sem bolhas e sem problemas. efetuando outros eventos que já estão sendo tratados. Algo como:
faz o truque!
fonte
Se você está chamando essa função a cada "clique", está adicionando outro par de manipuladores em cada chamada.
Adicionar manipuladores com jQuery não é como definir o valor do atributo "onclick". Pode-se adicionar quantos manipuladores desejar.
fonte
um evento será acionado várias vezes quando for registrado várias vezes (mesmo que para o mesmo manipulador).
por exemplo,
$("ctrl").on('click', somefunction)
se esse trecho de código for executado toda vez que a página for parcialmente atualizada, o evento também será registrado também. Portanto, mesmo que o ctrl seja clicado apenas uma vez que ele possa executar "alguma função" várias vezes - quantas vezes a execução dependerá de quantas vezes foi registrada.isso é verdade para qualquer evento registrado em javascript.
solução:
certifique-se de ligar "apenas" uma vez.
e por algum motivo, se você não puder controlar a arquitetura, faça o seguinte:
$("ctrl").off('click'); $("ctrl").on('click', somefunction);
fonte
Eu tive um problema por causa da marcação.
HTML:
jQuery
Você percebe que eu tenho a mesma classe 'myclass' duas vezes em html, então chama click para cada instância de div.
fonte
A melhor opção seria usar off
fonte
Todas as coisas sobre .on () e .one () são ótimas e o jquery é ótimo.
Mas, às vezes, você quer que seja um pouco mais óbvio que o usuário não tem permissão para clicar e, nesses casos, você pode fazer algo assim:
e seu botão ficaria assim:
fonte
Isso acontece porque o evento específico é vinculado várias vezes ao mesmo elemento.
A solução que funcionou para mim é:
Mate todos os eventos anexados usando o
.die()
métodoE então anexe seu ouvinte de método.
Portanto,
deveria estar:
fonte
Devemos
stopPropagation()
evitar o evento de gatilhos de cliques muitas vezes.Impede que o evento borbulhe na árvore DOM, impedindo que qualquer manipulador pai seja notificado sobre o evento. Este método não aceita argumentos.
Podemos usar
event.isPropagationStopped()
para determinar se esse método já foi chamado (nesse objeto de evento).Esse método também funciona para eventos personalizados acionados com trigger (). Observe que isso não impedirá a execução de outros manipuladores no mesmo elemento.
fonte
No meu caso, eu estava usando 'delegate', então nenhuma dessas soluções funcionou. Acredito que foi o botão exibido várias vezes por meio de chamadas ajax que estava causando o problema de vários cliques. As soluções estavam usando um tempo limite; portanto, apenas o último clique é reconhecido:
fonte
Documentos:
http://api.jquery.com/one/
fonte
fonte
.one é acionado apenas uma vez durante a vida útil da página
Portanto, caso você queira fazer a validação, essa não é a solução certa, porque quando você não sai da página após a validação, nunca mais volta. Melhor usar
fonte
Ao lidar com esse problema, sempre uso:
Desta forma, eu desdobro e volto no mesmo golpe.
fonte
https://jsfiddle.net/0vgchj9n/1/
Para garantir que o evento sempre seja acionado apenas uma vez, você pode usar o Jquery .one (). O JQuery one garante que seu manipulador de eventos seja chamado apenas uma vez. Além disso, você pode inscrever seu manipulador de eventos com um para permitir mais cliques quando terminar o processamento da operação de clique atual.
...
fonte
Tente assim:
fonte
No meu caso, o evento onclick foi disparado várias vezes porque eu havia feito um manipulador de eventos genérico comparativamente como
alterado para
e também precisa criar manipuladores separados para cliques estáticos e dinâmicos, para cliques estáticos na guia
fonte
No meu caso, eu carreguei o mesmo
*.js
arquivo na página duas vezes em uma<script>
tag, portanto os dois arquivos estavam anexando manipuladores de eventos ao elemento. Eu removi a declaração duplicada e isso corrigiu o problema.fonte
Outra solução que encontrei foi essa, se você tiver várias classes e estiver lidando com botões de opção enquanto clica no rótulo.
fonte
Eu estava tendo esse problema com um link gerado dinamicamente:
$(document).on('click', '#mylink', function({...do stuff...});
Eu encontrei a substituição
document
por'body'
corrigido o problema para mim:$('body').on('click', '#mylink', function({...do stuff...});
fonte
Unbind () funciona, mas isso pode causar outros problemas no futuro. O manipulador é acionado várias vezes quando está dentro de outro manipulador; portanto, mantenha seu manipulador fora e, se desejar os valores do manipulador aninhado, atribua-os a uma variável global que será acessível ao seu manipulador.
fonte
Caso isso funcione bem
fonte
O código abaixo funcionou para mim no meu aplicativo de bate-papo para lidar com vários eventos de acionamento de clique do mouse mais de uma vez.
if (!e.originalEvent.detail || e.originalEvent.detail == 1) { // Your code logic }
fonte