Как добавить съемный прослушиватель событий в список элементов, но при этом передать параметры вызываемой функции? - PullRequest
2 голосов
/ 31 марта 2020

У меня есть список элементов, хранящихся в переменной с именем elementList, и я хочу добавить прослушиватель событий для каждого из них. Итак, я создал следующее l oop:

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. Снова удалить прослушиватель событий, позже в коде

Спасибо за вашу помощь!

Ответы [ 2 ]

2 голосов
/ 31 марта 2020

Вы можете создать список функций и использовать их для удаления слушателя:

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
1 голос
/ 04 апреля 2020

Чтобы удалить прослушиватель событий с кнопки, вам потребуется ссылка на саму функцию. Поэтому перед использованием addEventListener сохраните функцию в объекте, в массиве или в другом месте, где вы можете оглянуться назад и найти эту функцию. Потому что removeEventListener не будет работать, если вы не дадите ему ту же функцию, которую вы использовали с addEventListener.

Ниже в фрагменте кода, который я построил, пример способа хранения эти слушатели событий и называют его 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(), чтобы l oop просмотреть все события в коллекции и прослушать их.

eventCollection.listen();

И всякий раз, когда вы захотите прекратить прослушивание событий в вашей коллекции, используйте следующее.

eventCollection.stopListening();
...