332

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

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

如果您有任何想法或建议,或者我的问题的解决方案是否类似于此处的另一个问题的解决方案,请告诉我(我查看了许多类似标题的线程,但没有找到可行的解决方案为了我)。

4

26 回答 26

601

要确保一次单击操作,请使用以下命令:

$(".bet").unbind().click(function() {
    //Stuff
});
于 2013-02-20T22:31:18.113 回答
432

.unbind()已弃用,您应该改用该.off()方法。只需.off()在您致电之前立即致电.on()

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

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

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

$(element).off('click').on('click', function() {
    // function body
});
于 2014-01-02T10:56:07.823 回答
165

。一()

更好的选择是.one()

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

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

如果有多个类,每个类都需要点击一次,

$(".bet").on('click',function() {
    //Your function
    $(this).off('click');   //or $(this).unbind()
});
于 2014-06-14T09:21:47.553 回答
104

如果您发现 .off() .unbind() 或 .stopPropagation() 仍然无法解决您的特定问题,请尝试使用.stopImmediatePropagation()在您只想处理您的事件而没有任何冒泡且没有冒泡的情况下效果很好影响已经处理的任何其他事件。就像是:

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

成功了!

于 2015-03-19T18:38:25.163 回答
18

如果您在每次“点击”时调用该函数,那么它会在每次调用时添加另一对处理程序。

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

于 2013-02-20T00:03:58.923 回答
16

一个事件在被多次注册时会触发多次(即使是同一个处理程序)。

例如$("ctrl").on('click', somefunction),如果每次页面部分刷新时都执行这段代码,那么每次都会注册事件。因此,即使 ctrl 仅被单击一次,它也可能多次执行“somefunction” - 它执行多少次取决于它被注册了多少次。

对于在 javascript 中注册的任何事件都是如此。

解决方案:

确保只调用一次“on”。

出于某种原因,如果您无法控制架构,请执行以下操作:

$("ctrl").off('click'); $("ctrl").on('click', somefunction);

于 2014-10-28T07:34:43.803 回答
8
$('.bed').one(function(){ })

文件:

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

于 2019-03-19T23:49:08.077 回答
4

我们必须stopPropagation()为了避免 Clicks 触发事件的次数过多。

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

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

我们可以event.isPropagationStopped()用来确定这个方法是否被调用过(在那个事件对象上)。

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

于 2015-01-20T05:22:16.463 回答
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) { ... } );

您注意到我在 html 中有两次相同的类“myclass”,因此它为每个 div 实例调用 click。

于 2015-09-18T09:58:44.763 回答
4

当我处理这个问题时,我总是使用:

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

这样我就可以在同一笔划中解绑和重新绑定。

于 2018-07-27T19:44:10.517 回答
3

更好的选择是使用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>
于 2016-08-08T06:19:26.880 回答
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>
于 2016-09-08T07:22:51.827 回答
2

发生这种情况是因为特定事件多次绑定到同一个元素。

对我有用的解决方案是:

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

然后附加您的方法侦听器。

因此,

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

应该:

$('.arrow').die("click")
$('.arrow').click(function() {
// FUNCTION BODY HERE
}
于 2013-10-10T07:40:04.917 回答
2

就我而言,我使用的是“代表”,所以这些解决方案都没有奏效。我相信是通过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)
})
于 2017-09-26T19:26:54.680 回答
1
$(element).click(function (e)
{
  if(e.timeStamp !== 0) // This will prevent event triggering more then once
   {
      //do your stuff
   }
}
于 2017-01-31T12:21:54.430 回答
1

.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
    }
});
于 2018-04-26T10:36:19.800 回答
1

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

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

我发现替换document'body'我解决了这个问题:

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

于 2019-03-21T19:40:22.887 回答
0

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

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

<div id="testDiv">
  <button class="testClass">Test Button</button>
</div>

…</p>

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();
于 2016-09-04T23:40:32.333 回答
0

试试这样:

<a href="javascript:void(0)" onclick="this.onclick = false; fireThisFunctionOnlyOnce()"> Fire function </a>
于 2018-05-30T11:36:15.133 回答
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;
    });`
于 2018-06-27T12:04:46.230 回答
0

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

于 2018-07-12T02:16:32.690 回答
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();
    }
});
于 2018-12-22T15:03:23.063 回答
0

如果这工作正常

$( "#ok" ).bind( "click", function() {
    console.log("click"); 
});
于 2020-02-14T14:56:35.143 回答
0

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

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

});
于 2021-06-12T08:39:21.117 回答
-1

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

于 2019-05-30T11:23:56.030 回答
-1

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

于 2019-10-15T06:13:58.503 回答