JavaScript: удалить прослушиватель событий


136

Я пытаюсь удалить слушателя события внутри определения слушателя:

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

Как я мог это сделать? это = событие ... Спасибо.


8
тривиально, но для будущих ссылок if(click == 50) {должно быть if( click === 50 )или if( click >= 50 )- они не изменят вывод, но по соображениям здравого смысла эти проверки имеют больше смысла.
rlemon

Хороший вопрос ... как мне удалить его, если у меня нет доступа к контенту? Я хочу удалить всплывающие окна для нажатия на кнопки с помощью greasemonkey для других сайтов, но, если я не могу ссылаться на функцию по имени, я, похоже, не найду способа удалить ее.
JasonXA

Ответы:


122

Вам нужно использовать именованные функции.

Кроме того, clickпеременная должна быть вне обработчика для приращения.

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

РЕДАКТИРОВАТЬ: Вы можете закрыть вокруг click_counterпеременной, как это:

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

Таким образом, вы можете увеличить счетчик по нескольким элементам.


Если вы этого не хотите и хотите, чтобы у каждого был свой счетчик, сделайте следующее:

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

РЕДАКТИРОВАТЬ: я забыл назвать имя обработчика, возвращаемого в последних двух версиях. Исправлена.


14
+1 - я превратил это в скрипку, и это не сработало. Но это потому, что мне нужно было нажать пятьдесят раз :) Какой я идиот. Упрощенный пример здесь: jsfiddle.net/karim79/aZNqA
karim79

4
@ karim79: Хотелось бы сказать, что никогда раньше такого не делал. : o) Спасибо за jsFiddle.
user113716

+1 Третий вариант у меня сработал. Назначение ключевого события в поле ввода для очистки проверки. Хорошая благодарность
Gurnard

Upvote, третий вариант здесь является важной частью понимания JS привязки / отмены привязки
SW4

будет myClick = function(event){...}считаться именованной функцией тоже?
Даниэль Мёллер

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

Должен сделать это.


14
Это здорово! Документ arguments.calleeдля заинтересованных сторон: developer.mozilla.org/en/JavaScript/Reference/…
конец

Спасибо, это очень помогло.
Джон

2
К сожалению, это не работает с ECMAScript 5 (2009) или более поздней версией из ссылки MDN: «5-я редакция ECMAScript (ES5) запрещает использование arguments.callee()в строгом режиме. Избегайте использования arguments.callee()либо путем присвоения выражений функции имени, либо использования объявления функции где функция должна вызывать себя ". (хотя он использует callee()вместо этого callee, он все еще удален, бу!)
Дай

59

Вы можете использовать выражение с именованной функцией (в этом случае функция именуется abc), например так:

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

Быстрый и грязный рабочий пример: http://jsfiddle.net/8qvdmLz5/2/ .

Дополнительная информация о выражениях именованных функций: http://kangax.github.io/nfe/ .


Умная. Один из тех редких случаев, когда NFE полезны. Спасибо.
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

Если решение @ Cybernate не работает, попробуйте отключить триггер для его собственной функции, чтобы вы могли ссылаться на нее.

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

4

Если кто-то использует jquery, он может сделать это так:

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

Надеюсь, что это может кому-то помочь. Обратите внимание, что ответ @ user113716 работает хорошо :)


2

Я думаю, что вам может потребоваться определить функцию-обработчик заранее, например так:

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

Это позволит вам удалить обработчик по имени изнутри себя.


-4

Попробуйте это, у меня получилось.

<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>
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.