代码之家  ›  专栏  ›  技术社区  ›  Gregory Fowler

jQuery点击事件触发多次

  •  344
  • Gregory Fowler  · 技术社区  · 13 年前

    我正试图用Javascript编写一个视频扑克游戏,以此来了解它的基本知识,但我遇到了一个问题,jQuery点击事件处理程序多次启动。

    它们连接在下注按钮上,在游戏中第一手下注(只发射一次)效果很好;但在为秒针下注时,每次按下下注或下注按钮时,它都会触发两次点击事件(因此每次按下都会下注两倍的正确金额)。总的来说,当按下一次下注按钮时,点击事件被触发的次数遵循这种模式——其中 第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
            }
        });
    }
    

    如果你有任何想法或建议,或者我的问题的解决方案是否与这里另一个问题的解决方法相似,请告诉我(我看了很多类似标题的线程,但没有找到一个对我有效的解决方案)。

    29 回复  |  直到 7 年前
        1
  •  628
  •   robsch YaakovHatam    9 年前

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

    $(".bet").unbind().click(function() {
        //Stuff
    });
    
        2
  •  453
  •   mtl    11 年前

    .unbind() 已弃用,您应该使用 .off() 方法。只需打电话 .off() 就在你打电话之前 .on() .

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

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

    要仅删除已注册的“单击”事件处理程序,请执行以下操作:

    $(element).off('click').on('click', function() {
        // function body
    });
    
        3
  •  172
  •   Shaunak D    11 年前

    .one()

    更好的选择是 .one() :

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

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

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

    $(".bet").on('click',function() {
        //Your function
        $(this).off('click');   //or $(this).unbind()
    });
    
        4
  •  115
  •   Alfonse Pinto    11 年前

    如果您发现.of().ubind()或.stopPropagation()仍然无法解决您的特定问题,请尝试使用 .stopImmediatePropagation() 当您只想在不冒泡的情况下处理您的事件,并且不影响已经处理的任何其他事件时,它非常有效。类似于:

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

    成功了!

        5
  •  19
  •   Kalpesh Popat    7 年前

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

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

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

    解决方案:

    确保只调用“on”一次。

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

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

        6
  •  18
  •   Pointy    13 年前

    如果你在每次“点击”时都调用该函数,那么 添加 每个调用上的另一对处理程序。

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

        7
  •  11
  •   double-beep hudson solomon    7 年前
    $('.bed').one(function(){ })
    

    文件:

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

        8
  •  6
  •   vimal1083    11 年前

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

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

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

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

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

        9
  •  4
  •   Bobz    11 年前

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

    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。

        10
  •  4
  •   Andy    8 年前

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

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

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

        11
  •  3
  •   arc_shiva    10 年前

    更好的选择是使用 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>
    
        12
  •  3
  •   rikkitikkitumbo    10 年前

    关于.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>
    
        13
  •  2
  •   Pupil    13 年前

    由于特定事件多次绑定到同一个元素,因此会发生这种情况。

    对我有效的解决方案是:

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

    然后连接你的方法监听器。

    因此

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

    应该是:

    $('.arrow').die("click")
    $('.arrow').click(function() {
    // FUNCTION BODY HERE
    }
    
        14
  •  2
  •   Trevor Lettman    9 年前

    在我的案例中,我使用的是“委托”,所以这些解决方案都不起作用。我相信是通过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)
    })
    
        15
  •  2
  •   nateM    7 年前

    我遇到了一个动态生成链接的问题:

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

    我发现正在替换 document 具有 'body' 为我解决了这个问题:

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

        16
  •  1
  •   Rajan Rajan M    9 年前
    $(element).click(function (e)
    {
      if(e.timeStamp !== 0) // This will prevent event triggering more then once
       {
          //do your stuff
       }
    }
    
        17
  •  1
  •   Pieter van Kampen    8 年前

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

    因此,如果你想进行验证,这不是正确的解决方案,因为当你在验证后不离开页面时,你就再也不会回来了。更好地使用

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

    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();
    
        19
  •  0
  •   Adam Kozlowski    8 年前

    试试看:

    <a href="javascript:void(0)" onclick="this.onclick = false; fireThisFunctionOnlyOnce()"> Fire function </a>
    
        20
  •  0
  •   Muhammad Awais    8 年前

    在我的案例中,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;
        });`
    
        21
  •  0
  •   inostia    8 年前

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

        22
  •  0
  •   Andrew Vink    7 年前

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

    $('.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();
        }
    });
    
        23
  •  0
  •   santosh vishwakarma    6 年前

    如果这样可以的话

    $( "#ok" ).bind( "click", function() {
        console.log("click"); 
    });
    
        24
  •  0
  •   ShapCyber    5 年前

    参考 @Pointy 答复 如果这个在循环中 ,可以通过这样做来避免多次触发点击事件:

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

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

        26
  •  0
  •   Kvvaradha    4 年前

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

    $("body").off("click", ".Element").on("click", ".Element", function(e){
         e.preventDefault();
        //Your code here 
    }); 
    
        27
  •  0
  •   Nabin    3 年前

    如果你只是这样写:

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

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

    如果您只想关闭特定按钮,请执行以下操作

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

        28
  •  -1
  •   user2792303    7 年前

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

        29
  •  -1
  •   praveen poonja    7 年前

    解除绑定()有效,但这可能会在将来引发其他问题。当处理程序在另一个处理程序内部时,它会多次触发,所以请将处理程序放在外部,如果您想要嵌套的处理程序的值,请将它们分配给一个全局变量,以便您的处理程序可以访问该全局变量。