删除事件侦听器香草 JS

Remove event listener vanilla JS

我有一个特殊的场景在这支笔中描述得尽可能简短:http://codepen.io/tuelsch/pen/rVRRNm?editors=101

这篇文章 (Adding and Removing Event Listeners with parameters) 为我指明了正确的方向,但设置不同。

我喜欢自定义 JS 对象 (Film),它可以在其 link 属性(一个 DOM 元素)上添加和删除事件处理程序。

我被第 18 行的 removeEvent 函数卡住了。在这种情况下,removeEventListener 函数的正确第二个参数是什么?

它没有添加和删除事件侦听器,而是不断添加事件侦听器,正如在记录第 8 行的结果的控制台中观察到的那样。

解决方案应该是普通的 JavaScript,兼容 ES5 并且旨在 运行 在浏览器 (IE9+) 中。

  1. 您可以先在您的对象中保留该绑定事件的记录,例如:
// Add the event handler
Film.prototype.bindEvent = function () {
  // This ensure that the binded event can be removed by removeEvent
  // even if you call bindEvent many times.
  if (!this._bindedEvent) {
    this._bindedEvent = this.eventHandler.bind(this);
    this.link.addEventListener('click', this._bindedEvent);
  }
}

然后删除:

// Remove the event handler
Film.prototype.removeEvent = function () {
  if (this._bindedEvent) {
    this.link.removeEventListener('click', this._bindedEvent); 
    this._bindedEvent = null;
  }
}

2。另一种方法是在构造函数中覆盖 eventhandler

// The test class definition
var Film = function () {
  this.link = document.getElementById('film');
  // This first find if self has attr eventHandler, and keep lookup to its prototype.
  // Then createa binded version of eventhandler and set to this's attr.
  // So when you try to access `this.eventHandler`, it'll be the binded version instead of Prototype's
  this.eventHandler = this.eventHandler.bind(this);
}

那你就可以用

// Add the event handler
Film.prototype.bindEvent = function () {
    this.link.addEventListener('click', this.eventHandler);
}

// Remove the event handler
Film.prototype.removeEvent = function () {
    this.link.removeEventListener('click', this.eventHandler); 
}

添加和删除它。

当您像此处那样使用 .bind(this) 时:this.link.addEventListener('click', this.eventHandler.bind(this)); 您实际上获得了一个新功能。当您尝试删除它时,您使用的是原始处理程序,并且删除找不到绑定的处理程序。

来自MDN

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

要修复此问题,请在定义处理程序时使用绑定(codepen - 处理程序将在 3 秒后删除):

// The event handler to add and remove
Film.prototype.eventHandler = function () {
  console.log('handled');
}.bind(Film);

// Add the event handler
Film.prototype.bindEvent = function () {
  this.link.addEventListener('click', this.eventHandler);
}

// Remove the event handler
Film.prototype.removeEvent = function () {
  this.link.removeEventListener('click', this.eventHandler);
}