【问题标题】:How can I add a removable event listener to a list of elements, but still pass parameters to the function it calls?如何将可移动事件侦听器添加到元素列表,但仍将参数传递给它调用的函数?
【发布时间】:2020-07-12 10:21:20
【问题描述】:

我有一个存储在名为elementList 的变量中的元素列表,并希望为每个元素添加一个事件侦听器。所以我创建了以下循环:

for (i = 0; i < elementList.length; i++) {
  elementList[i].addEventListener('click', myFunction, false);
}

问题?我需要将i 作为参数传递给myFunction。在网上做了一些研究后,我找到了这个解决方案:

for (i = 0; i < elementList.length; i++) {
  elementList[i].addEventListener('click', (function(i){
    return function(){
      myFunction(i);
    };
  }(i)), false);
}

代码运行良好——但仍然存在问题。稍后在我的代码中,我需要再次删除事件侦听器,这是通过 removeEventListener() 方法完成的,经过更多研究后我发现。

但是这个方法需要一个命名的外部函数——它不适用于匿名函数。所以它适用于我上面的第一个例子,但不适用于第二个。

所以我的问题是:如何将事件侦听器添加到元素列表中,这样我就可以同时做这两件事:

  1. 将参数传递给我的函数
  2. 在代码后面再次删除事件监听器

感谢您的帮助!

【问题讨论】:

  • @EmielZuurbier 我不确定。我知道如何在addEventListener 函数中传递参数,只是不知道如何以以后可以再次删除的方式进行。您提供的问题是否也提供了回答第二点的链接?

标签: javascript html function dom addeventlistener


【解决方案1】:

您可以生成函数列表并使用它们来移除监听器:

let removers = elementList.map((el, idx) => {
  let handler = () => myFunction(idx);
  el.addEventListener('click', handler);
  return () => el.removeEventListener('click', handler);
});

// when you need
//
removers[4]();  // calls removeEventListener

【讨论】:

  • 非常感谢您的回答!但是,我无法正确实现这一点。如果你有时间,你能检查一下我上面编辑过的问题吗?我在末尾添加了一个代码 sn-p 来解释我的意思。
  • @Run_Script 你在哪个版本的 ecmascript 中工作?
  • 抱歉,我不知道如何找到它。我添加到问题中的代码 sn-p 对您有用吗?它对我没有任何作用。
  • @Run_Script git 看看这个 jsfiddle jsfiddle.net/30dx7z5u
  • 非常感谢,我现在明白了!
【解决方案2】:

要从按钮中删除事件侦听器,您需要引用函数本身。因此,在使用addEventListener 之前,将函数存储在对象或数组中,或者您可以回顾并找到该函数的地方。因为如果您不提供与 addEventListener 使用的完全相同的功能,removeEventListener 将无法工作。

在下面的代码 sn-p 中,我构建了一个示例来存储这些事件侦听器并将其称为EventCollection。此类用作容器并保存要添加的每个事件的列表。这样您就可以随时在代码中添加或删除所有您想要的事件侦听器,而无需做太多工作。

class EventCollection {

  /**
   * Create a list to store the entries in.
   */
  constructor() {
    this.entries = [];
    this.isListening = false;
  }

  /**
   * Add an entry to the collection to listen for on an event.
   */
  append(target, type, listener, options = false) {
    if (!(target instanceof EventTarget)) return;
    this.entries.push({ target, type, listener, options });
    return this;
  }

  /**
   * Listen for all the entries in the list.
   */
  listen() {
    if (!this.isListening) {
      this.entries.forEach(({ target, type, listener, options }) => {
        target.addEventListener(type, listener, options);
      });
      this.isListening = true;
    }
    return this;
  }

  /**
   * Stop listening for all the entries in the list.
   */
  stopListening() {
    this.entries.forEach(({ target, type, listener, options }) => {
      target.removeEventListener(type, listener, options);
    });
    this.isListening = false;
    return this;
  } 

}

// Create a new instance of an EventCollection
var eventCollection = new EventCollection();

var buttons = document.getElementsByTagName('button');

function myFunction(index) {
  alert(index);
}

// Add all the event listeners to the collection.
for (var i = 0; i < buttons.length; i++) {
  (function(i){
    eventCollection.append(buttons[i], 'click', function() {
      myFunction(i);
    }, false);
  }(i));
}

// Start listening.
eventCollection.listen();

// After 5 seconds, stop listening.
// The buttons won't work anymore.
setTimeout(function() {
  eventCollection.stopListening();
}, 5000);
<button>Button 1</button>
<button>Button 2</button>
<button>Button 3</button>

像这样构建集合。使用new 关键字。

// Create a new collection
var eventCollection = new EventCollection();

下一步是添加您要收听的事件。它需要元素、事件类型和事件触发时调用的函数。

eventCollection.append(element, 'click', function() {});

现在您的事件已在集合中并已存储,但它们尚未侦听事件。使用.listen() 方法循环遍历集合中的所有事件并监听它们。

eventCollection.listen();

当您想停止收听集合中的事件时,请使用以下命令。

eventCollection.stopListening();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-23
    • 2011-09-18
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多