JavaScript: usuń detektor zdarzeń


136

Próbuję usunąć detektor zdarzeń wewnątrz definicji detektora:

canvas.addEventListener('click', function(event) {
    click++;
    if(click == 50) {
        // remove this event listener here!
    }
// More code here ...

Jak mogłem to zrobić? this = event ... Dziękuję.


8
trywialne, ale na przyszłość odniesienia if(click == 50) {powinny być if( click === 50 )lub if( click >= 50 )- nie zmienią wyniku, ale ze względów rozsądku te sprawdzenia mają więcej sensu.
rlemon

Dobre pytanie ... jak mogę to usunąć, jeśli nie mam dostępu do treści? Chcę usunąć wyskakujące okienka w celu kliknięcia przycisków za pomocą greasemonkey w innych witrynach, ale jeśli nie mogę odwołać się do funkcji według nazwy, nie znajduję sposobu na jej usunięcie.
JasonXA

Odpowiedzi:


121

Musisz użyć nazwanych funkcji.

Ponadto clickzmienna musi znajdować się na zewnątrz procedury obsługi, aby można ją było zwiększać.

var click_count = 0;

function myClick(event) {
    click_count++;
    if(click_count == 50) {
       // to remove
       canvas.removeEventListener('click', myClick);
    }
}

// to add
canvas.addEventListener('click', myClick);

EDYCJA: Możesz zamknąć click_counterzmienną w ten sposób:

var myClick = (function( click_count ) {
    var handler = function(event) {
        click_count++;
        if(click_count == 50) {
           // to remove
           canvas.removeEventListener('click', handler);
        }
    };
    return handler;
})( 0 );

// to add
canvas.addEventListener('click', myClick);

W ten sposób możesz zwiększyć licznik na kilka elementów.


Jeśli tego nie chcesz i chcesz, aby każdy z nich miał swój własny licznik, zrób to:

var myClick = function( click_count ) {
    var handler = function(event) {
        click_count++;
        if(click_count == 50) {
           // to remove
           canvas.removeEventListener('click', handler);
        }
    };
    return handler;
};

// to add
canvas.addEventListener('click', myClick( 0 ));

EDYCJA: zapomniałem nazwać handlera zwracanego w ostatnich dwóch wersjach. Naprawiony.


14
+1 - Zrobiłem z tego skrzypce i nie zadziałało. Ale to dlatego, że musiałem klikać pięćdziesiąt razy :) Co za idiota ze mnie. Uproszczony przykład tutaj: jsfiddle.net/karim79/aZNqA
karim79

4
@ karim79: Chciałbym móc powiedzieć, że nigdy wcześniej nie robiłem czegoś takiego. : o) Dzięki za jsFiddle.
user113716

+1 Trzecia opcja zadziałała dla mnie. Przypisanie kluczowego zdarzenia do pola wejściowego w celu wyczyszczenia walidacji. Miłe dzięki
Gurnard

Głos za, trzecia opcja tutaj jest ważna dla zrozumienia wiązania / rozpinania JS
SW4

byłaby myClick = function(event){...}również uważana za nazwaną funkcję?
Daniel Möller

80
   canvas.addEventListener('click', function(event) {
      click++;
      if(click == 50) {
          this.removeEventListener('click',arguments.callee,false);
      }

Powinienem to zrobić.


14
To jest fajne! Dokument arguments.calleedla zainteresowanych stron: developer.mozilla.org/en/JavaScript/Reference/ ...
Ender

Dzięki, to bardzo pomogło.
John O,

2
Niestety nie działa to z ECMAScript 5 (2009) lub nowszym, z linku do MDN: „Piąte wydanie ECMAScript (ES5) zabrania używania arguments.callee()w trybie ścisłym. Unikaj używania arguments.callee()poprzez nadawanie wyrażeniom funkcji nazwy lub użycie deklaracji funkcji gdzie funkcja musi wywołać samą siebie. " (chociaż używa callee()zamiast callee, jest nadal usuwany, boo!)
Dai

59

Możesz użyć nazwanego wyrażenia funkcyjnego (w tym przypadku funkcja jest nazwana abc), na przykład:

let click = 0;
canvas.addEventListener('click', function abc(event) {
    click++;
    if (click >= 50) {
        // remove event listener function `abc`
        canvas.removeEventListener('click', abc);
    }
    // More code here ...
}

Szybki i brudny przykład pracy: http://jsfiddle.net/8qvdmLz5/2/ .

Więcej informacji o nazwanych wyrażeniach funkcyjnych: http://kangax.github.io/nfe/ .


Sprytny. Jeden z tych rzadkich przypadków, w których NFE są przydatne. Dzięki.
DanMan

7
element.querySelector('.addDoor').onEvent('click', function (e) { });
element.querySelector('.addDoor').removeListeners();


HTMLElement.prototype.onEvent = function (eventType, callBack, useCapture) {
this.addEventListener(eventType, callBack, useCapture);
if (!this.myListeners) {
    this.myListeners = [];
};
this.myListeners.push({ eType: eventType, callBack: callBack });
return this;
};


HTMLElement.prototype.removeListeners = function () {
if (this.myListeners) {
    for (var i = 0; i < this.myListeners.length; i++) {
        this.removeEventListener(this.myListeners[i].eType, this.myListeners[i].callBack);
    };
   delete this.myListeners;
};
};

6

Jeśli rozwiązanie @ Cybernate nie działa, spróbuj przełamać wyzwalacz do jego własnej funkcji, aby móc się do niej odwołać.

clickHandler = function(event){
  if (click++ == 49)
    canvas.removeEventListener('click',clickHandler);
}
canvas.addEventListener('click',clickHandler);

4

Jeśli ktoś używa jquery, może to zrobić w ten sposób:

var click_count = 0;
$( "canvas" ).bind( "click", function( event ) {
    //do whatever you want
    click_count++;
    if ( click_count == 50 ) {
        //remove the event
        $( this ).unbind( event );
    }
});

Mam nadzieję, że może to komuś pomóc. Zauważ, że odpowiedź udzielona przez @ user113716 działa ładnie :)


2

Myślę, że możesz potrzebować zdefiniować funkcję handlera z wyprzedzeniem, na przykład:

var myHandler = function(event) {
    click++; 
    if(click == 50) { 
        this.removeEventListener('click', myHandler);
    } 
}
canvas.addEventListener('click', myHandler);

Umożliwi to usunięcie modułu obsługi według nazwy z samego siebie.


-4

Spróbuj tego, to zadziałało dla mnie.

<button id="btn">Click</button>
<script>
 console.log(btn)
 let f;
 btn.addEventListener('click', f=function(event) {
 console.log('Click')
 console.log(f)
 this.removeEventListener('click',f)
 console.log('Event removed')
})  
</script>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.