it-swarm.com.ru

события нажатия jQuery запускаются несколько раз

Я пытаюсь написать видео-покер на Javascript, чтобы разобраться с его основами, и столкнулся с проблемой, когда обработчики событий нажатия jQuery запускаются несколько раз.

Они прикреплены к кнопкам для размещения ставки, и это прекрасно работает для размещения ставки на первую руку во время игры (стрельба только один раз); но при ставке на вторую руку она запускает событие нажатия дважды каждый раз, когда нажимается кнопка ставки или ставки на ставку (таким образом, в два раза правильная сумма ставится на каждое нажатие). В целом, этот шаблон повторяется количество раз, когда событие нажатия срабатывает при однократном нажатии кнопки ставки - где термин последовательности ith относится к ставке руки ith с начала игра: 1, 2, 4, 7, 11, 16, 22, 29, 37, 46, которая, по-видимому, равна n (n + 1)/2 + 1 для чего бы то ни было - и я не был достаточно умен чтобы понять это, я использовал OEIS . :)

Вот функция с обработчиками событий click, которые работают; надеюсь, это легко понять (дайте мне знать, если нет, я тоже хочу стать лучше):

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

Пожалуйста, дайте мне знать, если у вас есть какие-либо идеи или предложения, или если решение моей проблемы похоже на решение другой проблемы здесь (я просмотрел много одноименных веток и не смог найти решение, которое могло бы работать для меня).

237
Gregory Fowler

Чтобы убедиться, что только клик действия, используйте это:

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

.unbind() устарела, и вы должны использовать метод .off() . Просто позвоните .off() прямо перед вызовом .on().

Это удалит все обработчики событий:

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

Чтобы удалить только зарегистрированные обработчики событий click

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

.один()

Лучшим вариантом будет .one():

Обработчик выполняется не более одного раза для каждого элемента для каждого типа события.

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

В случае нескольких классов, и каждый класс нужно нажать один раз,

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

Если вы обнаружите, что .off () .unbind () или .stopPropagation () по-прежнему не решают вашу конкретную проблему, попробуйте использовать .stopImmediatePropagation () отлично работает в ситуациях, когда вы просто хотите, чтобы ваше событие обрабатывалось без любое пузырение и без воздействия на любые другие события, которые уже обрабатываются. Что-то вроде:

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

делает трюк!

65
Alfonse Pinto

Если вы вызываете эту функцию при каждом «клике», то она добавляет другую пару обработчиков при каждом вызове.

Добавление обработчиков с помощью jQuery не похоже на установку значения атрибута «onclick». Можно добавить столько обработчиков, сколько пожелаете.

16
Pointy

это старая проблема, но я столкнулся с ней сегодня, и я думаю, что мой ответ поможет будущему искателю подобных проблем.

она выполняется несколько раз, потому что функция «on ('click', somefunction)» вызывается несколько раз, и, следовательно, она связывается несколько раз - для окончательного решения этой проблемы необходимо убедиться, что функция «on» находится в таком состоянии. место, что это будет выполнено только один раз. после чего при событии щелчка мышью функция сработает только один раз.

например, если я поставлю «on ('click', somefunction)» в месте, где он будет загружен дважды, то при каждом щелчке - «somefunction» будет запущен дважды.

в правильной логической последовательности функция «выкл.» должна использоваться только тогда, когда вы действительно намерены отменить привязку событий. использовать его для сокрытия логических ошибок, вызванных двойной загрузкой функции «вкл», не очень хороший подход, даже если может показаться, что он работает.

5
Kalpesh Popat

У меня была проблема из-за разметки.

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

Вы заметили, что у меня один и тот же класс 'myclass' дважды в html, поэтому он вызывает click для каждого экземпляра div.

4
Bobz

Все, что касается .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>
3
rikkitikkitumbo

Лучшим вариантом будет использовать выкл

<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>
2
arc_shiva

В моем случае я использовал «делегат», поэтому ни одно из этих решений не сработало. Я полагаю, что это была кнопка, появляющаяся много раз через вызовы 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)
})
2
Trevor Lettman
$('.bed').one(function(){ })

Docs:

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

2
Conner Gesbocker

Мы должны stopPropagation() Чтобы избежать кликов триггеров событие слишком много раз.

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

Это предотвращает всплытие события в DOM-дереве, предотвращая уведомление любых родительских обработчиков о событии. Этот метод не принимает никаких аргументов.

Мы можем использовать event.isPropagationStopped(), чтобы определить, был ли когда-либо вызван этот метод (для этого объекта события).

Этот метод также работает для пользовательских событий, запускаемых с помощью trigger (). Обратите внимание, что это не помешает запуску других обработчиков на том же элементе.

2
Daniel Raja Singh

Это происходит из-за того, что конкретное событие несколько раз связано с одним и тем же элементом.

Решение, которое сработало для меня:

Убейте все события, прикрепленные с помощью метода .die().

А затем прикрепите свой метод слушателя.

Таким образом, 

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

должно быть:

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

Когда я имею дело с этой проблемой, я всегда использую:

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

Таким образом, я развязываю и переплетаю одним махом.

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

.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
    }
});
0
Pieter van Kampen

Другое решение, которое я нашел, заключалось в следующем: если у вас несколько классов и вы работаете с переключателями, нажимая на ярлык.

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

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

Чтобы событие всегда срабатывало только один раз, вы можете использовать Jquery .one (). JQuery один гарантирует, что ваш обработчик событий вызывается только один раз. Кроме того, вы можете подписать свой обработчик событий на один, чтобы разрешить дальнейшие клики, когда вы закончите обработку текущей операции щелчка.

<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();
0
Razan Paul

У меня была эта проблема с динамически сгенерированной ссылкой:

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

Я обнаружил, что замена document на 'body' устранила проблему для меня:

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

0
nateM

В моем случае событие 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;
    });`
0
Awais Nasir

Попробуйте так:

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

В моем случае я дважды загружал один и тот же файл *.js на страницу в теге <script>, поэтому оба файла прикрепляли обработчики событий к элементу. Я удалил дубликат декларации, и это решило проблему.

0
inostia