Делегирование событий Vanilla JS - обработка дочерних элементов целевого элемента
Я пытаюсь выполнить делегирование событий в vanilla JS. У меня есть кнопка внутри контейнера вроде этого
<div id="quiz">
<button id="game-again" class="game-again"><span class="icon-spinner icon"></span><span>Go again</span></button>
</div>
И после Дэвид Уолш славные инструкции Я добавляю обработчик события к предку кнопки следующим образом:
this.container.addEventListener('click', function(e){
if (e.target && e.target.id == 'game-again') {
e.stopPropagation();
self.publish('primo:evento');
}
});
Где this.container - это элемент #quiz. Это работает в течение половины времени, но в остальное время цель события click является одним из интервалов внутри кнопки, поэтому мой обработчик событий не вызывается. Какой лучший способ справиться с этой ситуацией?
Ответы
Ответ 1
Используя .matches, вы можете найти этот polyfill полезным (ie9 +)
if (!Element.prototype.matches)
Element.prototype.matches =
Element.prototype.msMatchesSelector ||
Element.prototype.webkitMatchesSelector;
скопирован из эта страница mdn
Ответ 2
Новые браузеры
Новые браузеры поддерживают .matches
:
this.container.addEventListener('click', function(e){
if (e.target.matches('#game-again,#game-again *')) {
e.stopPropagation();
self.publish('primo:evento');
}
});
Вы можете получить неповрежденную версию с помощью
var matches = document.body.matchesSelector || document.body.webkitMatchesSelector || document.body.mozMatchesSelector || document.body.msMatchesSelector || document.body.webkitMatchesSelector || document.body.matchesSelector
И затем используйте .apply
для большего количества браузеров (Still IE9 +).
Старые браузеры
Предполагая, что вам нужно поддерживать старые браузеры, вы можете подойти к DOM:
function hasInParents(el,id){
if(el.id === id) return true; // the element
if(element.parentNode) return hasInParents(el.parentNode,id); // a parent
return false; // not the element nor its parents
}
Однако это приведет к восхождению на весь дом, и вы хотите остановиться на цели делегирования:
function hasInParentsUntil(el,id,limit){
if(el.id === id) return true; // the element
if(el === limit) return false;
if(element.parentNode) return hasInParents(el.parentNode,id); // a parent
return false; // not the element nor its parents
}
Что, сделает ваш код:
this.container.addEventListener('click', function(e){
if (hasInParentsUntil(e.target,'game-again',container)) { // container should be
e.stopPropagation(); // available for this
self.publish('primo:evento');
}
});