JavaScript:删除事件侦听器

tho*_*mas 118 javascript events event-handling listener

我正在尝试删除侦听器定义中的事件侦听器:

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

我怎么能这样做?这=事件......谢谢.

use*_*716 110

您需要使用命名函数.

此外,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);
Run Code Online (Sandbox Code Playgroud)

编辑:您可以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);
Run Code Online (Sandbox Code Playgroud)

这样,您可以跨多个元素递增计数器.


如果你不想那样,并希望每个人都有自己的计数器,那么这样做:

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 ));
Run Code Online (Sandbox Code Playgroud)

编辑: 我忘了在最后两个版本中命名返回的处理程序.固定.

  • +1 - 我把它变成了一个小提琴而且它不起作用.但那是因为我需要点击五十次:)我真是个白痴.这里的简化示例:http://jsfiddle.net/karim79/aZNqA/ (13认同)
  • @ karim79:我希望我能说我以前从未做过这样的事情.:o)感谢jsFiddle. (3认同)

ede*_*ett 75

   canvas.addEventListener('click', function(event) {
      click++;
      if(click == 50) {
          this.removeEventListener('click',arguments.callee,false);
      }
Run Code Online (Sandbox Code Playgroud)

应该这样做.

  • 请注意,这在ECMAScript5严格模式下不起作用. (51认同)
  • 这很酷!有关各方的`arguments.callee`文档:https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments/callee (13认同)
  • 不幸的是,这不适用于 ECMAScript 5 (2009) 或更高版本,来自 MDN 链接:“ECMAScript (ES5) 的第 5 版禁止在严格模式下使用 `arguments.callee()`。避免使用 `arguments.callee( )` 通过为函数表达式命名或使用函数声明(其中函数必须调用自身)。” (虽然它使用 `callee()` 而不是 `callee`,但它仍然被删除了,嘘!) (9认同)

Tam*_*ama 45

您可以使用命名函数表达式(在本例中为函数命名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 ...
}
Run Code Online (Sandbox Code Playgroud)

快速而肮脏的工作示例:http://jsfiddle.net/WqpfZ/1/.

有关命名函数表达式的更多信息:http://kangax.github.io/nfe/.


Bra*_*tie 10

如果@Cyber​​nate 的解决方案不起作用,请尝试将触发器分解为它自己的功能,以便您可以引用它。

clickHandler = function(event){
  if (click++ == 49)
    canvas.removeEventListener('click',clickHandler);
}
canvas.addEventListener('click',clickHandler);
Run Code Online (Sandbox Code Playgroud)


Mik*_*ans 8

看起来没有人涵盖当前 JavaScript DOM 规范的一部分,该规范为您提供了一种无需使用removeEventListener. 如果我们查看https://dom.spec.whatwg.org/#concept-event-listener,我们会发现有许多属性可以传递来控制事件监听:

{
  type (a string)
  callback (null or an EventListener object)
  capture (a boolean, initially false)
  passive (a boolean, initially false)
  once (a boolean, initially false)
  signal (null or an AbortSignal object)
  removed (a boolean for bookkeeping purposes, initially false) 
}
Run Code Online (Sandbox Code Playgroud)

现在,该列表中有很多有用的属性,但为了删除事件侦听器,signal我们想要使用它的属性(已于 2020 年底添加到 DOM 级别 3 ),因为它允许我们发送一个中止信号,让 JS 完成剩下的工作,而不需要将我们的事件处理函数保存在某个地方,然后使用removeEventListener与我们注册监听器完全相同的参数组合进行调用:

{
  type (a string)
  callback (null or an EventListener object)
  capture (a boolean, initially false)
  passive (a boolean, initially false)
  once (a boolean, initially false)
  signal (null or an AbortSignal object)
  removed (a boolean for bookkeeping purposes, initially false) 
}
Run Code Online (Sandbox Code Playgroud)

(注意,这并没有使用该useCapture标志,因为useCapture标志本质上是完全没用的)

完成:一旦调用,JS 引擎将中止并清理我们的事件监听器controller.abort(),而不必使用removeEventListener与我们调用完全相同的函数和属性进行调用addEventListener:只需取消监听器即可。


Vin*_*ows 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;
};
};
Run Code Online (Sandbox Code Playgroud)


End*_*der 5

我认为您可能需要提前定义处理程序函数,如下所示:

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

这将允许您从处理程序内部按名称删除处理程序。