Удаление события не работает

Я пытаюсь написать свою собственную систему делегирования событий, и она прекрасно работает, за исключением того, что я не могу удалить событие, как только присоединяю его к элементу! Я рвал на себе волосы, пытаясь понять это. Любая помощь будет принята с благодарностью.

Код в ручке: http://codepen.io/anon/pen/BjyZyV?editors=101

А также ниже:

наценка

<ul id="parent">
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
  <li class="item">Lorum</li>
</ul>

Javascript

Element.prototype.matches = Element.prototype.matches || Element.prototype.msMatchesSelector;

function isDescendant(parents, child) {
  for (var i = 0; i < parents.length; i++) {
    var node = child.parentNode;
    while (node !== null) {
      if (node === parents[i]) {
        return true;
      }
      node = node.parentNode;
    }
  }
  return false;
}

function eventCallback(e) {
  if (e.target && e.target.matches(this.options.selector)) {
    this.options.callback.call(this, e);
  } else if (isDescendant(this.parent.querySelectorAll(this.options.selector), e.target)) {
    this.options.callback.call(this, e);
  }
}

var MyEvent = {
  register: function register(options) {
    this.parent = document.querySelector(options.parentSelector);
    this.options = options;

    this.parent.addEventListener(options.event, eventCallback.bind(this), false);

    return this;
  },
  unregister: function unregister(options) {
    this.parent = document.querySelector(options.parentSelector);

    this.parent.removeEventListener(options.event, eventCallback, false);

    return this;
  }
};

myEvent = Object.create(MyEvent);

myEvent.register({
  event: 'click',
  parentSelector: '#parent',
  selector: '.item',
  callback: function(e) {
    alert('clicked!');
  }
});

myEvent.unregister({
  event: 'click',
  parentSelector: '#parent'
});

1 ответ

Решение

Вопрос с bind(), он возвращает новую функцию.
Из документации

Метод bind() создает новую функцию, которой при вызове присваивается ключевое слово this с указанным значением, причем заданная последовательность аргументов предшествует предоставленным при вызове новой функции.

Так что каждый раз, когда вы звоните bind Вы получаете совершенно новую функцию, например, здесь

this.parent.addEventListener(options.event, eventCallback.bind(this), false);

это так же, как

var brandNewFunction = eventCallback.bind(this); // creates new function

this.parent.addEventListener(options.event, brandNewFunction, false);

Таким образом, вы не передаете функцию eventCallback вообще, вы передаете новую функцию, следовательно, ее нельзя удалить с помощью

this.parent.removeEventListener(options.event, eventCallback, false);

как ты никогда не проходил eventCallbackи функции должны быть одинаковыми для removeEventListener чтобы иметь возможность удалить слушателя.
Решение, конечно, назвать это так

this.parent.addEventListener(options.event, eventCallback, false);

и найдите какой-нибудь другой умный способ передать ваши варианты и т. д.

Другие вопросы по тегам