关于javascript:jQuery单击事件多次触发

jQuery click events firing multiple times

我试图用Javascript编写一个视频扑克游戏作为一种获取它的基础知识的方法,并且我遇到了jQuery点击事件处理程序多次触发的问题。

它们附在用于下注的按钮上,并且它适用于在比赛期间在第一手牌上下注(仅发射一次);但是在投注秒针时,每次按下下注或下注按钮时,它都会触发点击事件两次(因此每次按下两次正确的金额)。总的来说,它遵循这种模式,按下一次下注按钮时点击事件被触发的次数 - 其中序列的第i个术语是从游戏开始时第i个手的投注:1,2,4 ,7,11,16,22,29,37,46,对于任何值得的东西来说似乎是n(n + 1)/ 2 + 1 - 而且我还不够聪明,我用过OEIS 。 :)

这是使用单击事件处理程序的函数;希望它很容易理解(如果没有,请告诉我,我也希望在这方面做得更好):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/** 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
        }
    });
}

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


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

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


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

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

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

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

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


。一()

.one()是一个更好的选择:

The handler is executed at most once per element per event type.

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

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

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


如果您发现.off()。unbind()或.stopPropagation()仍然无法解决您的具体问题,请尝试使用.stopImmediatePropagation()在您只希望处理事件时不需要任何冒泡且没有任何冒泡的情况下工作得很好影响已经处理的任何其他事件。就像是:

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

诀窍!


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

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


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

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

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

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


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

HTML:

1
   Click Me

jQuery的

1
$('.myclass').on('click', 'a', function(event) { ... } );

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


关于.on()和.one()的所有东西都很棒,jquery很棒。

但有时候,你希望用户不被允许点击更明显,在这种情况下你可以这样做:

1
2
3
4
5
6
7
8
9
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);
}

你的按钮看起来像:

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


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

文档:

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


它发生的原因是特定事件多次绑定到同一个元素。

对我有用的解决方案是:

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

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

从而,

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

应该:

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

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

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

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

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

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


在我的情况下,我使用'委托',所以这些解决方案都没有奏效。我相信这是通过ajax调用多次出现导致多次点击问题的按钮。解决方案使用超时,因此只识别最后一次点击:

1
2
3
4
5
6
7
8
9
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)
})

更好的选择是使用off

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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...");
});

1
2
3
4
5
6
7
$(element).click(function (e)
{
  if(e.timeStamp !== 0) // This will prevent event triggering more then once
   {
      //do your stuff
   }
}


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

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

这样我就可以解开并重新绑定。


.one仅在页面的生命周期内触发一次

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

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

试试这个:

1
 Fire function

在我的情况下,onclick事件多次被触发,因为我已经将通用事件处理程序作为比较

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

变成

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

并且还必须为静态和动态点击制作单独的处理程序,以便进行静态选项卡单击

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

在我的情况下,我在标签中将页面上的相同*.js文件加载了两次,因此两个文件都将事件处理程序附加到元素。我删除了重复的声明,并修复了问题。


我找到的另一个解决方案是,如果你有多个类,并且在点击标签时处理单选按钮。

1
2
3
4
5
6
7
8
9
$('.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();
    }
});

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

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

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

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


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

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

1
  <button class="testClass">Test Button</button>

...

1
2
3
4
5
6
7
8
9
10
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();

以下代码在我的聊天应用程序中为我工作,可以多次处理多个鼠标单击触发事件。
<5233>