繁体   English   中英

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

这是 function 和正在运行的点击事件处理程序; 希望它很容易理解(如果不明白请告诉我,我也想在这方面做得更好):

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

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

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

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

.unbind()已弃用,您应该改用.off()方法。 只需拨打.off()调用正确的之前.on()

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

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

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

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

。一()

更好的选择是.one()

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

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

在多个类的情况下,每个类都需要点击一次,

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

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

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

行得通!

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

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

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

例如$("ctrl").on('click', somefunction)如果这段代码在每次页面部分刷新时都执行,则每次都会注册该事件。 因此,即使 ctrl 只被点击一次,它也可能多次执行“某个功能”——它执行的次数将取决于它被注册的次数。

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

解决方案:

确保只调用一次“on”。

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

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

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

文档:

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

由于标记,我遇到了问题。

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。

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

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

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

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

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

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

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

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

对我有用的解决方案是:

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

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

因此,

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

应该:

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

就我而言,我使用的是“委托”,因此这些解决方案均无效。 我相信是通过 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)
})

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

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

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

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

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

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

试试这样:

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

就我而言,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;
    });`

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

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

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

如果这工作正常

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

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

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

});

使用 Event.stopPropagation()。 它会起作用的。

这个解决方案对我有用。 当您的元素添加动态时,您需要这样做才能实现它。 这个答案可能是为了将来检查用户。

$("body").off("click", ".Element").on("click", ".Element", function(e){
     e.preventDefault();
    //Your code here 
}); 

如果你只是这样写:

$(document).off('click').on("click", "#btnID", function(){ })

然后,它将禁用所有项目的点击事件。

如果您只想关闭单击特定按钮,请执行此操作

$(document).off('click', "#btnID").on("click", "#btnID", function(){ })

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM