여러 번 실행되는 jQuery 클릭 이벤트


283

비디오 포커 게임의 기초를 내리는 방법으로 자바 포커로 비디오 포커 게임을 작성하려고하는데 jQuery 클릭 이벤트 핸들러가 여러 번 실행되는 문제가 발생했습니다.

베팅을하기위한 버튼에 부착되어 있으며, 게임 중에 직접 베팅을 할 때 좋습니다 (한 번만 발사). 그러나 초침 베팅에서는 베팅 또는 플레이스 베팅 버튼을 누를 때마다 클릭 이벤트가 두 번 발생합니다 (따라서 매번 정확한 금액이 베팅됩니다). 베팅 버튼을 한 번 누르면 클릭 이벤트가 발생하는 횟수에 대해 전반적으로이 패턴을 따릅니다 . 시퀀스 의 i 번째 항은 게임 시작부터 i 번째 손을 베팅 한 것입니다 . 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
        }
    });
}

아이디어 나 제안 사항이 있거나 내 문제에 대한 해결책이 여기의 다른 문제에 대한 해결책과 비슷한 지 알려주십시오. 나를 위해).


var amount = parseInt(this.id.replace(/[^\d]/g,''),10);요소의 동일한 속성을 두 번 이상 사용하여 해당 속성을 캐시 하려는 경우 계속 찾아 보지 마십시오. 조회 비용이 비싸다.
David는 Monica를

응답 및 캐싱 특성에 대한 팁을 주셔서 감사합니다. 나는 player.money와 player.bet을 지역 변수 돈으로 설정하고 그 함수 내에서 내기를 걸고 대신 그 코드를 조작하고 나머지 코드도 변경하도록 변경합니다. :) 시간이 있으면 제안한 것을 설명 할 수 있습니까? 금액 초기화가 진행 중입니다. 정규 표현식처럼 보이지만 쉽게 이해할 수는 없습니다.
그레고리 파울러

@GregoryFowler-귀하의 질문과 관련이 없지만 ... javascript switch 문을 살펴볼 가치가 있습니다.
Clayton

2
Man, 함수는 호출 될 때마다 클릭 핸들러를 배치합니다. 각 라운드에서 호출하면 2 라운드에 두 개의 핸들러가 있습니다. 각 처리기는 작업을 수행하고 100 라운드에서 100 개의 경고를받습니다.
Marco Faustinelli 2016 년

이것은 코드 어딘가에서 이벤트 핸들러를 바인딩 해제하지 않고 리 바인드하기 때문에 발생합니다. 비슷한 시나리오 및 좋은 설명 은이 질문을 참조하십시오 .
jpaugh

답변:


526

한 번만 클릭 동작을 수행하려면 다음을 사용하십시오.

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

31
알았어 어제 어디에 있었어, Rob? ;) 정확히 내가 찾던 것인데, 왜 내가 그것을 찾지 못했는지 모르겠습니다. 그러나 나는 다른 많은 것들을 배웠기 때문에 여전히 변장의 축복이었습니다.
그레고리 파울러

1
;) 죄송합니다. 나는 이것에 몇 일 동안 내 바퀴를 돌렸다. 나는 왜 그것이 처음부터 일어나는지에 대한 논리적 인 이유를 찾고 있습니다.
Rob

6
이렇게 많은 일을 한 사람. 내 경우를 제외하고는 다음과 같습니다. $ ( ". bet"). off (). on ()
MadTurki

7
jroi_web이 아래에 언급했듯이이 방법은 더 이상 사용되지 않습니다. 최신 솔루션은 @trolle의 답변을 참조하십시오.
Pascal

클릭 핸들러는 일회성 문제가 아닙니다. 특히 질문에 표시된 부피가 큰 경우에는 특히 그렇습니다. 당신은 그것을 첨부하고 페이지가 존재하는 한 그것이 작동하도록해야합니다.
Marco Faustinelli 2016 년

378

.unbind()더 이상 사용되지 않으며 .off()대신 메소드를 사용해야합니다 . 전화 .off()하기 직전에 전화하십시오 .on().

모든 이벤트 핸들러가 제거됩니다.

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

등록 된 'click'이벤트 핸들러 만 제거하려면 다음을 수행하십시오.

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

9

매력처럼 작동합니다! 내 함수는 클릭 한 번, 두 번, 네 번 ... .on () 전에이 문제를 해결하기 전에 .off () 실행됩니다.
jumpOnCommand

146

.하나()

더 나은 옵션은 다음과 .one()같습니다.

핸들러는 이벤트 유형 당 요소 당 최대 한 번 실행됩니다.

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

여러 수업이 있고 각 수업을 한 번 클릭해야하는 경우,

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

8
가장 좋은 대답, 당신은 바보 같은 해킹에서 나를 구원이 훨씬 더 그 때문에 여러 경우 onclick같은 요소에 있지만 다른 위치에있는 사건이 나머지에 영향을 미치지 않습니다, 동안 unbind()off()단지 다른 파괴 onclick의 당신을 다시 감사합니다
Fanckush

3
모든 답변을 시도한 후에, 이것은 나를위한 유일한 작품입니다.
neversion

10
참고로 한 번 클릭하면 함수가 한 번만 실행되고 후속 클릭에서 계속 실행되도록하려면 페이지 수명 동안 문자 그대로 한 번만 실행됩니다. 따라서 off (). on () 메소드에 대한 mtl의 대답을 사용해야합니다.
Derek Hewitt

1
@ munchschair에는 여러 가지 이유가 있습니다. 서로 같은 클래스를 가진 여러 요소. 또는 클릭 핸들러가 반복적으로 여러 번 등록됩니다.
Shaunak D

3
나를 위해 작동하지 않음-여전히 여러 번의 클릭 발생-ID가있는 단 하나의 버튼 요소 만 있고 하나의 이벤트 만 잡히기 때문에 (클릭 이벤트) 의미가 없습니다. 나는 이것이 jQuery 버그라고 생각했지만 아마도 부트 스트랩 모달 대화 버그 일 것입니다.
MC9000

78

.off () .unbind () 또는 .stopPropagation ()이 여전히 특정 문제를 해결하지 못한다면 .stopImmediatePropagation ()을 사용해보십시오. 버블 링없이 또는 이벤트없이 이벤트를 처리하려는 경우에 효과적입니다. 이미 처리중인 다른 이벤트에 영향을줍니다. 다음과 같은 것 :

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

트릭을 수행합니다!


이것은 이벤트가 두 번 발생하는 것을 막는 것뿐만 아니라 나를 도왔습니다. jQuery UI 대화 상자 필드에 연결된 이벤트 핸들러에서 event.stopImmediatePropagation ()을 사용하면 어떤 이유로 대화 상자가 더 이상 최신 글로벌 변수 인스턴스를 참조 할 수 없으며 대신 전역 변수 버전을 사용하는 것으로 나타났습니다 jQuery UI 대화 상자 렌더링 전에. 예를 들어, 전역 변수가 선언되었지만 jQuery UI 대화 상자 렌더링시 초기화되지 않은 경우 초기화되지 않은 jQuery UI 대화 상자 이벤트 핸들러로 표시됩니다.
UkraineTrain

1
또는 jQuery UI 대화 상자를 렌더링하기 전에 일부 전역 변수에 16 값을 할당하면 나중에 55로 변경됩니다. 그러면 16이 jQuery UI 대화 상자 이벤트 핸들러에 해당 전역 변수에 대해 16이 표시됩니다. 더 이상 16. 따라서 사람들이 알아야 할 jQuery UI 버그처럼 보입니다.
UkraineTrain

설명하기 어려운 특정 상황의 경우. "다른 이벤트에는 영향을주지 않고 작동합니다." 감사합니다! :)
Toms Bugna

나를 위해 완벽하게 작동합니다. 감사!
Somnath Pawar

18

"클릭"할 때마다 해당 함수를 호출하면 각 호출에 다른 핸들러 쌍이 추가 됩니다.

jQuery로 핸들러를 추가하는 것은 "onclick"속성의 값을 설정하는 것과 다릅니다. 하나의 원하는만큼 많은 핸들러를 추가 할 수 있습니다.


4
귀하의 답변이 올바른 방향으로 설정되었고 많은 것을 배웠지 만 불행히도 jQuery를 사용하여 문제를 해결하기에는 충분하지 않습니다. :) on / off, live (and delegate) / die 및 one을 사용한 다음 addEventListener / removeEventListener를 사용해 보았지만 처리기의 기하 급수적 인 증가 속도를 늦추는 것이 최선이었습니다. 결국 한동안 onclick과 관련된 문제를 해결했습니다. 그러나 나는 아직도 당신의 대답에서 캡처 / 버블 링과 같은 Javascript의 이벤트 모델에 대해 많은 것을 배웠으므로 감사합니다. 감사합니다. :)
Gregory Fowler

정말 고마워요, 이걸 몰랐어요!
Lenny

12

이벤트가 여러 번 등록되면 이벤트가 여러 번 발생합니다 (같은 핸들러에 있더라도).

예를 들어 $("ctrl").on('click', somefunction)페이지를 부분적으로 새로 고칠 때마다이 코드 조각이 실행되면 매번 이벤트도 등록됩니다. 따라서 Ctrl 키를 한 번만 클릭해도 "일부 기능"을 여러 번 실행할 수 있습니다. 실행 횟수는 등록 된 횟수에 따라 다릅니다.

이것은 자바 스크립트에 등록 된 모든 이벤트에 해당됩니다.

해결책:

"on"을 한 번만 호출하십시오.

어떤 이유로 든 아키텍처를 제어 할 수없는 경우 다음을 수행하십시오.

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


당신이 정말로 말하고 싶은 것?
Somnath Kharat

이 경우에 무슨 일이 일어나고 있는지 설명하지 않습니다. 버튼에는 하나의 고유 ID와 하나의 이벤트 만 있습니다 (한 번만 클릭 할 수 있으므로 여러 번 호출되지 않음). 이것은 jQuery 대화 상자에만 나타나는 버그이며 매우 쉽게 재현 할 수 있습니다.
MC9000

2
"pushingBetButtons"함수가 한 번 또는 여러 번 호출되는지 여부를 알 수 없습니다. 두 번 이상 호출되면 이벤트가 여러 번 등록되므로 여러 번 실행됩니다. 버튼을 한 번만 클릭하더라도 .
Kalpesh Popat 2012

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을 호출합니다.


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>

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>

1
사용자가 실제로 여러 번 클릭하는 경우를 해결하지만 동일한 타임 스탬프로 여러 클릭 이벤트가 발생합니다. 내가 너무 빠르 더라도 (그리고 어떻게 버튼을 몇 번 누르는지 알지 못 하더라도) 동일한 밀리 초에 3 번 클릭 할 수있는 방법이 없습니다 .
jpaugh

2

특정 이벤트가 동일한 요소에 여러 번 바인드되어 발생합니다.

나를 위해 일한 해결책은 다음과 같습니다.

를 사용하여 첨부 된 모든 이벤트를 종료 .die()메소드를 .

그런 다음 메소드 리스너를 연결하십시오.

그러므로,

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

해야한다:

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

2

stopPropagation()클릭 트리거 이벤트가 너무 많이 발생하지 않도록 해야합니다 .

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

이벤트가 DOM 트리를 버블 링하는 것을 방지하여 상위 핸들러가 이벤트를 통지하지 못하게합니다. 이 메소드는 인수를 허용하지 않습니다.

event.isPropagationStopped()이 메소드가 해당 이벤트 오브젝트에서 호출되었는지 여부를 판별 하는 데 사용할 수 있습니다 .

이 메소드는 trigger ()로 트리거 된 커스텀 이벤트에도 적용됩니다.이 메소드는 동일한 요소의 다른 핸들러가 실행되는 것을 막지 않습니다.


2

필자의 경우 '대리인'을 사용하고 있었으므로 이러한 솔루션 중 아무것도 작동하지 않았습니다. 여러 번의 클릭 문제를 일으키는 아약스 호출을 통해 여러 번 나타나는 버튼이라고 생각합니다. 솔루션에서 시간 초과를 사용하여 마지막 클릭 만 인식되었습니다.

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


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

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

1

이 문제를 다룰 때 항상 다음을 사용합니다.

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

이 방법으로 동일한 스트로크에서 바인딩을 해제하고 리 바인드합니다.


0

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

0

그런 식으로 시도하십시오 :

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

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

0

필자의 경우 *.js페이지 에서 동일한 파일을 <script>태그에 두 번 로드 했으므로 두 파일 모두 이벤트 핸들러를 요소에 첨부했습니다. 중복 선언을 제거하고 문제를 해결했습니다.


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

0

동적으로 생성 된 링크 에서이 문제가 발생했습니다.

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

나는 대체 발견 document'body'나를 위해 고정 된 문제 :

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


0

바인드 해제 ()는 작동하지만 나중에 다른 문제가 발생할 수 있습니다. 처리기는 다른 처리기 내에있을 때 여러 번 트리거되므로 처리기를 외부에 유지하고 중첩 된 처리기의 값을 원하면 처리기에 액세스 할 수있는 전역 변수에 할당하십시오.



-1

아래 코드는 채팅 응용 프로그램에서 여러 마우스 클릭 트리거 이벤트를 두 번 이상 처리하는 데 효과적이었습니다. if (!e.originalEvent.detail || e.originalEvent.detail == 1) { // Your code logic }

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.