如何删除 JavaScript 事件侦听器?

How can I remove a JavaScript event listener?

提问人:thomas 提问时间:12/10/2010 最后编辑:isherwoodthomas 更新时间:3/30/2023 访问量:366303

问:

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

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

我该怎么做?这 = 事件...

JavaScript 事件 事件处理 侦听器

评论

11赞 rlemon 3/15/2012
微不足道,但对于将来的引用应该是 OR - 它们不会改变输出,但出于理智的原因,这些检查更有意义。if(click == 50) {if( click === 50 )if( click >= 50 )
0赞 JasonXA 6/27/2015
问得好。。。如果我无权访问内容,如何删除它?我想为其他站点使用 greasemonkey 删除 onclick 按钮的弹出窗口,但除非我可以按名称引用该函数,否则我似乎找不到删除它的方法。

答:

13赞 Brad Christie 12/10/2010 #1

如果 @Cybernate 的解决方案不起作用,请尝试将触发器分解到它自己的函数中,以便您可以引用它。

clickHandler = function(event){
  if (click++ == 49)
    canvas.removeEventListener('click',clickHandler);
}
canvas.addEventListener('click',clickHandler);
186赞 user113716 12/10/2010 #2

您需要使用命名函数。

此外,变量需要位于处理程序之外才能递增。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 ));

评论

0赞 SW4 5/19/2015
赞成,这里的第三个选项是理解 JS 绑定/解绑的重要组成部分
0赞 Daniel Möller 7/29/2015
也会被视为命名函数吗?myClick = function(event){...}
0赞 Daniel Möller 7/29/2015
我想知道我是否可以做:,然后和最后??myClick = function....another = myClickremoveEventListener('click', another)
0赞 alebianco 12/20/2016
@Daniel 因为返回一个函数,你当然可以myClick(0)
1赞 Mike 'Pomax' Kamermans 7/27/2022
请注意,虽然在 2010 年是正确的,但自 2020 年底为事件引入控制信号以来,情况就不是这样了。您不再需要命名函数,甚至不再需要命名函数:如今您可以直接中止事件removeEventListener
5赞 Ender 12/10/2010 #3

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

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

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

100赞 edeverett 12/10/2010 #4
   canvas.addEventListener('click', function(event) {
      click++;
      if(click == 50) {
          this.removeEventListener('click',arguments.callee,false);
      }

应该这样做。

评论

17赞 Ender 12/10/2010
这很酷!相关人士文档:developer.mozilla.org/en/JavaScript/Reference/...arguments.callee
12赞 Dai 5/30/2020
不幸的是,这不适用于 ECMAScript 5 (2009) 或更高版本,来自 MDN 链接:“ECMAScript (ES5) 第 5 版禁止在严格模式下使用避免使用函数表达式的名称或使用函数声明,其中函数必须调用自身。(虽然它正在使用 而不是 ,但它仍然被删除,嘘!arguments.callee()arguments.callee()callee()callee
8赞 Vinyl Windows 5/31/2012 #5
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;
};
};
97赞 Tama 1/7/2014 #6

您可以使用命名函数表达式(在本例中为函数命名),如下所示: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/

4赞 youssman 8/8/2014 #7

如果有人使用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给出的答案效果很好:)

-7赞 user3870075 11/5/2016 #8

试试这个,它对我有用。

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

评论

0赞 Psuedodoro 6/10/2022
然而,这并不是一个帮助人们的好做法......
6赞 Mike 'Pomax' Kamermans 7/23/2022 #9

看起来没有人涵盖当前 JavaScript DOM 规范的一部分,该规范为您提供了一种在不使用 .如果我们看一下 https://dom.spec.whatwg.org/#concept-event-listener 我们会发现有许多属性可以传递来控制事件侦听: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) 
}

现在,该列表中有很多有用的属性,但为了删除事件侦听器,它是我们想要使用的属性(在 2020 年底添加到 DOM 级别 3),因为它让我们告诉 JS 引擎通过调用来删除事件侦听器,而不必费心:signalabort()removeEventListener

const canvasListener = (new AbortController()).signal;

canvas.addEventListener('click', () => {
  click++;
  if (click === 50) {
    canvasListener.abort();
  } else {
    doSomethingWith(click);
  }
}, {
  signal: canvasListener 
});

(请注意,这不使用标志,因为useCapture标志基本上是完全无用的)useCapture

完成:JS 引擎将中止并清理我们的事件侦听器。没有保留对处理函数的引用,没有确保我们调用的属性与我们调用的完全相同:我们只是取消侦听器。removeEventListeneraddEventListener

-2赞 Luis Americo 8/15/2022 #10

实现此目的的一种方法是使用 jquery,因此您可以使用:

canvas.click(yourfunction);

然后,您可以使用以下命令分离所有事件侦听器:

canvas.off();

评论

1赞 Carnix 9/24/2022
jQuery已经过时了,无论如何,OP都没有询问jQuery框架。
0赞 Andrea Lazzarotto 4/20/2023
“jQuery已过时”[需要引用]
2赞 Carnix 9/15/2023
@AndreaLazzarotto 简单:youmightnotneedjquery.com ES6 使 jQuery 变得不必要。jQuery现在唯一真正想要的就是一个现成的插件环境......但是,在任何生产环境中依赖不受信任的第三方开发人员代码无论如何都是一种愚蠢的风险,尤其是当您找到该插件时可能不受支持时。别忘了:jQuery是JavaScript,所以它只是臃肿,你总是可以做jQuery在vanilla JS中所做的任何事情。碰巧的是,现代 ECMAScript 现在基本上和 jQuery 一样简单。
0赞 Umair Ahmed 12/2/2023
@Carnix 你在某种程度上是对的。显然,JQuery 一直是可以在 JS 中完成的事情。实际上,这不是你可以反对任何事情的东西。拥有由其他人维护的 API 而不是由您维护的 API 几乎是 JQuery 和任何其他 JS 库所要做的。出于某种原因,它在前 100 万个站点中的使用率高达 78%。尽管如此,我还是希望拥有比 vanilla 和 JQuery 更好的东西,但这不是 React。