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

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

user113716
источник
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);
      }

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

edeverett
источник
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 работает хорошо :)

youssman
источник
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>
user3870075
источник