web-dev-qa-db-ja.com

jQueryクリックイベントが複数回発生する

その基本を理解するためにJavascriptでビデオポーカーゲームを作成しようとしていますが、jQueryのクリックイベントハンドラが複数回起動されるという問題に遭遇しました。

それらは賭けをするためのボタンに付けられていて、ゲーム中に最初に賭けをするのにうまく働きます(一度だけ発射する)。しかし、セカンドハンドへのベットでは、ベットボタンまたはプレースベットボタンが押されるたびにクリックイベントが2回発生します(つまり、各プレスで正しい金額の2倍がベットされます)。概して、それはベットボタンを一回押すときクリックイベントが発生する回数の間このパターンに従います - ここでシーケンスのi項はi手の賭けのためのものです1、2、4、7、11、16、22、29、37、46、1、2、4、7、11、16、22、29、37、46、これは価値のあるものなら何でもn - (n + 1)/ 2 + 1 - そして私は駄目それを理解するのに十分賢くはないので、 _ oeis _ を使用しました。 :)

これが、クリックイベントハンドラが機能している機能です。うまくいけば、理解するのは簡単です(そうでない場合は私に知らせてください、私もその点で良くなりたいです)。

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

何かアイデアや提案がある場合、または私の問題の解決策がこちらの別の問題の解決策に似ているかどうかを教えてください(私は似たようなタイトルのスレッドをたくさん見ましたが、うまくいく解決策を見つけられませんでした)私のために)。

248
Gregory Fowler

クリックのみのアクションを確実にするには、これを一度使用します。

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

.unbind()は非推奨であり、代わりに .off() メソッドを使用してください。 .off()を呼び出す直前に、単に.on()を呼び出してください。

これにより、すべてのイベントハンドラが削除されます。

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

登録されたクリックイベントハンドラのみを削除するには:

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

。1()

より良いオプションは.one()です。

ハンドラは、イベントタイプごとに要素ごとに最大1回実行されます。

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

複数のクラスがあり、各クラスを一度クリックする必要がある場合は、

$(".bet").on('click',function() {
    //Your function
    $(this).off('click');   //or $(this).unbind()
});
128
Shaunak D

それでも.off()、.unbind()、または.stopPropagation()を実行しても問題が解決しない場合は、 .stopImmediatePropagation() を使用してみてください。バブリングすることなく、またすでに処理中の他のイベントに影響を与えることなく処理されます。何かのようなもの:

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

トリックをします!

65
Alfonse Pinto

あなたが "クリック"するたびにその関数を呼んでいるのであれば、それは 追加 それぞれの呼び出しでもう一対のハンドラです。

JQueryでハンドラを追加することは、単に "onclick"属性の値を設定することとは異なります。望むだけの数のハンドラを追加することができます。

16
Pointy

それは古い問題ですが、私は今日それに直面しました、そして私の答えは同様の課題の将来の探求者に役立つと思います。

"on( 'click'、somefunction)"関数が複数回呼び出されているため複数回バインドされているため、これは複数回実行されます。一度だけ実行される場所その後、マウスクリックイベントで、関数は一度だけ起動されます。

たとえば、「on( 'click'、somefunction)」を2回読み込まれる場所に配置した場合、クリックするたびに「somefunction」が2回起動されます。

論理的に正しい順序で "off"関数を使うのは、本当にイベントをアンバインドしようとしているときだけにしてください。 "on"関数の二重ロードによって引き起こされる論理エラーを隠すためにそれを使用することは、たとえそれが機能しているように見えても良い方法ではありません。

5
Kalpesh Popat

マークアップのせいで問題がありました。

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

私はhtmlで同じクラス 'myclass'を2回持っているので、divの各インスタンスに対してclickを呼び出します。

4
Bobz

.on()と.one()に関するすべてのものは素晴らしいです、そしてjqueryは素晴らしいです。

しかし、時には、ユーザーがクリックを許可されていないことをもう少し明確にしたい場合があります。その場合は、次のようにすることができます。

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

ボタンは次のようになります。

<button onclick='funName()'>Click here</button>
3
rikkitikkitumbo

より良い方法は 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

私の場合は「代理人」を使用していたので、これらの解決策はどれもうまくいきませんでした。私はそれがマルチクリックの問題を引き起こしていたのは、Ajax呼び出しを介して複数回現れるボタンであったと思います。解決策はタイムアウトを使用していたので、最後のクリックだけが認識されます。

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(){ })

ドキュメント:

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

2

Clicksがイベントを何度もトリガーしないようにするには、stopPropagation()を実行する必要があります。

$(this).find('#cameraImageView').on('click', function(evt) {
   evt.stopPropagation();
   console.log("Camera click event.");
});

イベントがDOMツリーを膨らませるのを防ぎ、親ハンドラにイベントが通知されるのを防ぎます。このメソッドは引数を取りません。

このメソッドが(そのイベントオブジェクトに対して)呼び出されたことがあるかどうかを判断するためにevent.isPropagationStopped()を使用できます。

このメソッドは、trigger()でトリガーされたカスタムイベントにも機能します。これにより、同じ要素上の他のハンドラーの実行が妨げられることはありません。

2

特定のイベントが同じ要素に複数回バインドされているために発生します。

私のために働いた解決策は、次のとおりです。

.die()メソッドを使用して添付されたすべてのイベントを終了させます。

そして、メソッドリスナーを添付してください。

したがって、

$('.arrow').click(function() {
// FUNCTION BODY HERE
}

する必要があります:

$('.arrow').die("click")
$('.arrow').click(function() {
// FUNCTION BODY HERE
}
2
Pupil

私がこの問題に取り組むとき、私はいつも使用します:

$(".bet").unbind("click").bind("click", function (e) {
  // code goes here
}

このように私はアンバインドし、同じストロークで再バインドします。

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はページの存続期間中に一度だけ起動します。

そのため、検証を行いたい場合、これは正しい解決策ではありません。検証後にページを終了しないと、戻ってこないからです。使うほうがいい

$(".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

あなたが複数のクラスを持っていて、ラベルをクリックしている間にラジオボタンを扱っているならば、私が見つけたもう一つの解決策はこれでした。

$('.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/ /

イベントが常に一度だけ発生するようにするには、Jquery .one()を使用します。 JQueryはあなたのイベントハンドラが一度だけ呼び出されることを保証します。さらに、現在のクリック操作の処理が終了したときにさらにクリックできるように、イベントハンドラを1つ登録することができます。

<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

私は動的に生成されたリンクでこの問題を抱えていました:

$(document).on('click', '#mylink', function({...do stuff...});

document'body'に置き換えると問題が解決しました。

$('body').on('click', '#mylink', function({...do stuff...});

0
nateM

私の場合は、onclickイベントが複数回起動していました

  `$('div').on("click", 'a[data-toggle="tab"]',function () {
        console.log("dynamic bootstrap tab clicked");
        var href = $(this).attr('href');
        window.location.hash = href;
   });`

に変更

    `$('div#mainData').on("click", 'a[data-toggle="tab"]',function () {
        console.log("dynamic bootstrap tab clicked");
        var href = $(this).attr('href');
        window.location.hash = href;
    });`

また、静的タブクリック用に、静的クリック用と動的クリック用に別々のハンドラを作成する必要があります。

    `$('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

そのようにしてみてください。

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

私の場合は、同じ*.jsファイルを<script>タグでページに2回ロードしていたので、どちらのファイルもイベントハンドラを要素に添付していました。私は重複した宣言を削除して問題を解決しました。

0
inostia