it-swarm.com.de

jQuery-Klickereignisse, die mehrmals ausgelöst werden

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).

237
Gregory Fowler

Um sicherzustellen, dass ein Klick nur einmal ausgeführt wird, verwenden Sie Folgendes:

$(".bet").unbind().click(function() {
    //Stuff
});
442
Rob

.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
});
331
mtl

.ein()

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()
});
125
Shaunak D

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!

65
Alfonse Pinto

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.

17
Pointy

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.

5
Kalpesh Popat

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.

4
Bobz

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>
3
rikkitikkitumbo

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>
2
arc_shiva

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)
})
2
Trevor Lettman
$('.bed').one(function(){ })

Dokumente:

http://api.jquery.com/one/

2

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.

2

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
}
2
Pupil

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.

1
Andy
$(element).click(function (e)
{
  if(e.timeStamp !== 0) // This will prevent event triggering more then once
   {
      //do your stuff
   }
}
1
Rajan Rajan M

.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
    }
});
0

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();
    }
});
0
Andrew Vink

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();
0
Razan Paul

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...});

0
nateM

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;
    });`
0
Awais Nasir

Versuchen Sie es so:

<a href="javascript:void(0)" onclick="this.onclick = false; fireThisFunctionOnlyOnce()"> Fire function </a>
0
Adam Kozlowski

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.

0
inostia