Ich versuche, ein Video-Pokerspiel in Javascript zu schreiben, um die Grundlagen zu verbessern, und ich bin auf ein Problem gestoßen, bei dem die jQuery-Click-Ereignishandler mehrmals ausgelöst werden.
Sie sind an Schaltflächen angebracht, um eine Wette zu platzieren, und es funktioniert gut, wenn Sie während des Spiels eine Wette auf die erste Hand setzen (nur einmal feuern); Beim Wetten auf den Sekundenzeiger wird jedoch das Klickereignis jedes Mal zweimal ausgelöst, wenn eine Wette oder eine Platzwette gedrückt wird (daher wird bei jedem Drücken zweimal der richtige Betrag eingesetzt). Insgesamt folgt dieses Muster für die Häufigkeit, mit der das Klickereignis ausgelöst wird, wenn ein Bet-Button einmal gedrückt wird - wobei der Begriff ith der Sequenz für das Wetten der Hand ith von Anfang an gilt das Spiel: 1, 2, 4, 7, 11, 16, 22, 29, 37, 46, was für jeden Wert n (n + 1)/2 + 1 zu sein scheint - und ich war nicht schlau genug Um das herauszufinden, habe ich OEIS verwendet. :)
Hier ist die Funktion mit den Click-Ereignishandlern, die sich verhalten; hoffentlich ist es leicht zu verstehen (lass es mich wissen, wenn nicht, ich möchte auch das verbessern):
/** 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
}
});
}
Bitte lassen Sie mich wissen, ob Sie irgendwelche Ideen oder Vorschläge haben oder ob die Lösung für mein Problem einer Lösung für ein anderes Problem ähnelt. Ich habe viele ähnliche Threads angeschaut und hatte kein Glück, eine Lösung zu finden, die funktionieren könnte für mich).
Um sicherzustellen, dass ein Klick nur einmal ausgeführt wird, verwenden Sie Folgendes:
$(".bet").unbind().click(function() {
//Stuff
});
.unbind()
ist veraltet und Sie sollten stattdessen die Methode .off()
verwenden. Rufen Sie einfach .off()
auf, bevor Sie .on()
aufrufen.
Dadurch werden alle Event-Handler entfernt:
$(element).off().on('click', function() {
// function body
});
So entfernen Sie nur registrierte "click" -Ereignishandler:
$(element).off('click').on('click', function() {
// function body
});
Eine bessere Option wäre .one()
:
Der Handler wird höchstens einmal pro Element pro Ereignistyp ausgeführt.
$(".bet").one('click',function() {
//Your function
});
Bei mehreren Klassen muss jede Klasse einmal angeklickt werden.
$(".bet").on('click',function() {
//Your function
$(this).off('click'); //or $(this).unbind()
});
Wenn Sie feststellen, dass .off () .unbind () oder .stopPropagation () Ihr spezifisches Problem immer noch nicht behoben haben, versuchen Sie es mit .stopImmediatePropagation () Blasenbildung und ohne Auswirkungen auf andere bereits behandelte Ereignisse. So etwas wie:
$(".bet").click(function(event) {
event.stopImmediatePropagation();
//Do Stuff
});
macht den Trick!
Wenn Sie diese Funktion bei jedem "Klick" aufrufen, ist es Hinzufügen ein weiteres Handlerpaar bei jedem Aufruf.
Das Hinzufügen von Handlern mit jQuery entspricht nicht dem Festlegen des Werts des Attributs "onclick". Man kann beliebig viele Handler hinzufügen.
es ist ein altes Problem, aber ich bin heute damit konfrontiert, und ich denke, meine Antwort wird für zukünftige Sucher mit ähnlichen Herausforderungen hilfreich sein.
es wird mehrmals ausgeführt, da die Funktion "on (" click ", somefunction) mehrmals aufgerufen wird und daher mehrmals gebunden wird. Um dies dauerhaft zu lösen, müssen Sie sicherstellen, dass die Funktion" on "in einer solchen Funktion enthalten ist Stellen Sie sicher, dass es nur einmal ausgeführt wird. Danach wird die Funktion beim Mausklick-Ereignis nur einmal ausgelöst.
wenn ich zum Beispiel "on ('click', somefunction)" an einer Stelle anbringe, an der es zweimal geladen wird, wird bei jedem Klick - "somefunction" zweimal ausgelöst.
in einer korrekten logischen Reihenfolge sollte die Funktion "off" nur verwendet werden, wenn Sie die Ereignisse wirklich lösen möchten. es für das Ausblenden der logischen Fehler zu verwenden, die durch das doppelte Laden der Funktion "on" verursacht werden, ist kein guter Ansatz, auch wenn es anscheinend funktioniert.
Ich hatte ein Problem wegen Markup.
HTML:
<div class="myclass">
<div class="inner">
<div class="myclass">
<a href="#">Click Me</a>
</div>
</div>
</div>
jQuery
$('.myclass').on('click', 'a', function(event) { ... } );
Sie stellen fest, dass ich dieselbe Klasse 'myclass' zweimal in html habe, daher ruft click für jede Instanz von div auf.
Das ganze Zeug über .on () und .one () ist großartig und Jquery ist großartig.
Manchmal möchten Sie jedoch, dass es offensichtlicher ist, dass der Benutzer nicht klicken darf. In solchen Fällen können Sie Folgendes tun:
function funName(){
$("#orderButton").prop("disabled", true);
// do a bunch of stuff
// and now that you're all done
setTimeout(function(){
$("#orderButton").prop("disabled",false);
$("#orderButton").blur();
}, 3000);
}
und dein Knopf würde wie folgt aussehen:
<button onclick='funName()'>Click here</button>
Die bessere Option wäre die Verwendung von off
<script>
function flash() {
$("div").show().fadeOut("slow");
}
$("#bind").click(function() {
$( "body" )
.on("click", "#theone", flash)
.find("#theone")
.text("Can Click!");
});
$("#unbind").click(function() {
$("body")
.off("click", "#theone", flash)
.find("#theone")
.text("Does nothing...");
});
</script>
In meinem Fall habe ich 'Delegate' verwendet, also hat keine dieser Lösungen funktioniert. Ich glaube, es war die Schaltfläche, die mehrmals durch Ajax-Aufrufe angezeigt wurde, die das Problem mit mehreren Klicks verursachte. Bei den Lösungen wurde ein Timeout verwendet, sodass nur der letzte Klick erkannt wird:
var t;
$('body').delegate( '.mybutton', 'click', function(){
// clear the timeout
clearTimeout(t);
// Delay the actionable script by 500ms
t = setTimeout( function(){
// do something here
},500)
})
Wir müssen stopPropagation()
, um zu vermeiden, dass Clicks ein Ereignis zu oft auslöst.
$(this).find('#cameraImageView').on('click', function(evt) {
evt.stopPropagation();
console.log("Camera click event.");
});
Verhindert, dass das Ereignis die DOM-Struktur aufwirbelt, und verhindert, dass übergeordnete Handler über das Ereignis benachrichtigt werden. Diese Methode akzeptiert keine Argumente.
Wir können event.isPropagationStopped()
verwenden, um festzustellen, ob diese Methode jemals aufgerufen wurde (für dieses Ereignisobjekt).
Diese Methode funktioniert auch für benutzerdefinierte Ereignisse, die mit trigger () ausgelöst werden. Beachten Sie, dass dies nicht die Ausführung anderer Handler auf demselben Element verhindert.
Dies geschieht, weil das bestimmte Ereignis mehrmals an dasselbe Element gebunden ist.
Die Lösung, die für mich funktioniert hat, ist:
Beenden Sie alle angehängten Ereignisse mit der .die()
-Methode.
Und dann bringen Sie Ihren Methoden-Listener an.
Somit,
$('.arrow').click(function() {
// FUNCTION BODY HERE
}
sollte sein:
$('.arrow').die("click")
$('.arrow').click(function() {
// FUNCTION BODY HERE
}
Wenn ich mich mit diesem Problem beschäftige, verwende ich immer:
$(".bet").unbind("click").bind("click", function (e) {
// code goes here
}
Auf diese Weise löse ich die Bindung und baue sie im selben Hub wieder.
$(element).click(function (e)
{
if(e.timeStamp !== 0) // This will prevent event triggering more then once
{
//do your stuff
}
}
.one feuert nur einmal während der gesamten Lebensdauer der Seite
Falls Sie eine Validierung durchführen möchten, ist dies nicht die richtige Lösung. Wenn Sie die Seite nach der Validierung nicht verlassen, kommen Sie nie wieder zurück. Besser zu benutzen
$(".bet").on('click',function()
{ //validation
if (validated) {
$(".bet").off('click'); //prevent to fire again when we are not yet off the page
//go somewhere
}
});
Eine andere Lösung, die ich gefunden habe, war diese, wenn Sie mehrere Klassen haben und beim Anklicken des Labels Optionsfelder verwenden.
$('.btn').on('click', function(e) {
e.preventDefault();
// Hack - Stop Double click on Radio Buttons
if (e.target.tagName != 'INPUT') {
// Not a input, check to see if we have a radio
$(this).find('input').attr('checked', 'checked').change();
}
});
https://jsfiddle.net/0vgchj9n/1/
Um sicherzustellen, dass das Ereignis immer nur einmal ausgelöst wird, können Sie Jquery .one () verwenden. JQuery one sorgt dafür, dass Ihr Event-Handler nur einmal aufgerufen wird. Außerdem können Sie Ihren Event-Handler mit einem Abonnement abonnieren, um weitere Klicks zuzulassen, wenn Sie die Verarbeitung des aktuellen Klickvorgangs abgeschlossen haben.
<div id="testDiv">
<button class="testClass">Test Button</button>
</div>
…
var subscribeClickEvent = function() {$("#testDiv").one("click", ".testClass", clickHandler);};
function clickHandler() {
//... perform the tasks
alert("you clicked the button");
//... subscribe the click handler again when the processing of current click operation is complete
subscribeClickEvent();
}
subscribeClickEvent();
Ich hatte dieses Problem mit einem dynamisch generierten Link:
$(document).on('click', '#mylink', function({...do stuff...});
Ich habe festgestellt, dass das Ersetzen von document
durch 'body'
das Problem für mich behoben hat:
$('body').on('click', '#mylink', function({...do stuff...});
In meinem Fall wurde ein Onclick-Ereignis mehrfach ausgelöst, da ich einen generischen Event-Handler erstellt hatte
`$('div').on("click", 'a[data-toggle="tab"]',function () {
console.log("dynamic bootstrap tab clicked");
var href = $(this).attr('href');
window.location.hash = href;
});`
gewechselt zu
`$('div#mainData').on("click", 'a[data-toggle="tab"]',function () {
console.log("dynamic bootstrap tab clicked");
var href = $(this).attr('href');
window.location.hash = href;
});`
außerdem müssen separate Handler für statische und dynamische Klicks und statische Tabstopps erstellt werden
`$('a[data-toggle="tab"]').on("click",function () {
console.log("static bootstrap tab clicked");
var href = $(this).attr('href');
window.location.hash = href;
});`
Versuchen Sie es so:
<a href="javascript:void(0)" onclick="this.onclick = false; fireThisFunctionOnlyOnce()"> Fire function </a>
In meinem Fall hatte ich dieselbe *.js
-Datei zweimal in einem <script>
-Tag auf die Seite geladen, sodass beide Dateien Ereignisbehandlungsroutinen an das Element anfügten. Ich habe die doppelte Deklaration entfernt und damit das Problem behoben.