jQuery单击事件多次触发

时间:2013-02-20 00:02:17

标签: javascript jquery javascript-events click

我正在尝试用Javascript编写视频扑克游戏,以此来了解它的基础知识,并且我遇到了jQuery点击事件处理程序多次触发的问题。

它们附加在用于下注的按钮上,并且它适用于在游戏期间在第一手牌上下注(仅发射一次);但是在投注秒针时,每次按下下注或下注按钮时,它都会触发点击事件两次(因此每次按下两次正确的金额)。总的来说,它遵循这种模式,按下一次下注按钮时点击事件被触发的次数 - 其中 ith 项的序列用于投注 ith 从比赛开始的手: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
        }
    });
}

如果您有任何想法或建议,或者我的问题的解决方案与此处的另一个问题的解决方案类似,请告诉我(我已经查看了许多类似标题的主题并且没有找到解决方案的运气这对我有用。)

26 个答案:

答案 0 :(得分:464)

要确保只使用一次点击操作,请执行以下操作:

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

答案 1 :(得分:345)

不推荐使用

.unbind(),您应该使用.off()方法。只需在致电.off()之前致电.on()

这将删除所有事件处理程序:

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

仅删除已注册的“点击”事件处理程序:

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

答案 2 :(得分:128)

.one()

更好的选择是 .one()

  

每个事件类型的每个元素最多执行一次处理程序。

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

如果有多个班级,每个班级需要点击一次,

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

答案 3 :(得分:65)

如果您发现.off()。unbind()或.stopPropagation()仍然无法解决您的具体问题,请尝试使用.stopImmediatePropagation()在您只希望处理事件时任何冒泡并且不影响已经处理的任何其他事件。类似的东西:

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

诀窍!

答案 4 :(得分:16)

如果您在每次“点击”时调用该功能,则每次通话时添加另一对处理程序。

使用jQuery添加处理程序与设置“onclick”属性的值不同。可以根据需要添加尽可能多的处理程序。

答案 5 :(得分:5)

这是一个老问题,但我今天面对它,我认为我的答案将有助于未来寻求类似挑战。

它被执行多次,因为“on('click',somefunction)”函数被多次调用,因此它被多次绑定 - 为了永久解决这个问题,你需要确保“on”函数是在这样一个只执行一次的地方。在鼠标单击事件之后,该函数将仅被触发一次。

例如,如果我将“on('click',somefunction)”放在一个将被加载两次的地方,那么每次点击 - “somefunction”将被触发两次。

在正确的逻辑序列中,只有当您真正打算取消绑定事件时,才应使用“off”函数。使用它来隐藏由于“on”函数的双重加载而导致的逻辑错误,即使它看似有效也不是一个好方法。

答案 6 :(得分:4)

我因为标记而遇到了问题。

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

你注意到我有同一个班级&#39; myclass&#39;在html中两次,所以它为每个div实例调用click。

答案 7 :(得分:3)

关于.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>

答案 8 :(得分:2)

就我而言,我正在使用&#39; delegate&#39;,因此这些解决方案都不起作用。我相信这是通过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)
})

答案 9 :(得分:2)

$('.bed').one(function(){ })

文档:

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

答案 10 :(得分:2)

更好的选择是使用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>

答案 11 :(得分:2)

我们必须stopPropagation()为了避免点击次数触发事件太多次。

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

它阻止事件冒泡DOM树,防止任何父处理程序被通知事件。此方法不接受任何参数。

我们可以使用event.isPropagationStopped()来确定是否曾调用此方法(在该事件对象上)。

此方法也适用于使用trigger()触发的自定义事件。请注意,这不会阻止同一元素上的其他处理程序运行。

答案 12 :(得分:2)

这是因为特定事件多次绑定到同一个元素。

对我有用的解决方案是:

使用.die()方法杀死所有附加的事件。

然后附加你的方法监听器。

因此,

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

应该是:

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

答案 13 :(得分:1)

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

答案 14 :(得分:1)

在处理此问题时,我始终使用:

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

这样,我可以在同一笔划中解除绑定并重新绑定。

答案 15 :(得分:0)

https://jsfiddle.net/0vgchj9n/1/

要确保事件始终只触发一次,您可以使用Jquery .one()。 JQuery one确保您的事件处理程序只调用一次。此外,您可以使用一个订阅事件处理程序,以便在完成当前单击操作的处理后允许进一步单击。

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

答案 16 :(得分:0)

。只会在页面的生命周期内触发一次

因此,如果您想进行验证,这不是正确的解决方案,因为当您在验证后不离开页面时,您永远不会回来。最好使用

$(".bet").on('click',function() 
{ //validation 
   if (validated) { 
      $(".bet").off('click'); //prevent to fire again when we are not yet off the page
      //go somewhere
    }
});

答案 17 :(得分:0)

尝试这种方式:

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

答案 18 :(得分:0)

在我的情况下,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;
    });`

答案 19 :(得分:0)

就我而言,我在页面上的*.js标签中两次加载了相同的<script>文件,因此这两个文件都将事件处理程序附加到元素上。我删除了重复的声明,并解决了问题。

答案 20 :(得分: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();
    }
});

答案 21 :(得分:0)

我在使用动态生成的链接时遇到了这个问题:

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

我发现用document代替'body'为我解决了这个问题:

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

答案 22 :(得分:0)

Unbind()有效,但是将来可能会导致其他问题。该处理程序在另一个处理程序中时会多次触发,因此请将您的处理程序置于外部,如果您希望嵌套的处理程序的值,请将它们分配给一个全局变量,您的处理程序将可以访问该全局变量。

答案 23 :(得分:0)

以防万一

$( "#ok" ).bind( "click", function() {
    console.log("click"); 
});

答案 24 :(得分:0)

参考 @Pointy 答案。 如果这是在循环中,则可以通过执行以下操作来避免多次触发点击事件:

 $(".bet").each(function(i,item){
       $(this).on({
            click:function(){
                //TRIGGERS ONES
            if(i){
              console.log(i); 
                //DO YOUR THING HERE
            }
            
            }
        });

});

答案 25 :(得分:-1)

以下代码在我的聊天应用程序中为我工作,可以多次处理多个鼠标单击触发事件。 if (!e.originalEvent.detail || e.originalEvent.detail == 1) { // Your code logic }