Реализация jQuery "живого" связующего с собственным Javascript
Я пытаюсь выяснить, как связать событие с динамически создаваемыми элементами. Мне нужно, чтобы событие сохранялось на элементе даже после его уничтожения и восстановления.
Очевидно, что с живой функцией jQuery это легко, но что бы они выглядели как реализованные с помощью собственного Javascript?
Ответы
Ответ 1
Вот простой пример:
function live(eventType, elementId, cb) {
document.addEventListener(eventType, function (event) {
if (event.target.id === elementId) {
cb.call(event.target, event);
}
});
}
live("click", "test", function (event) {
alert(this.id);
});
Основная идея заключается в том, что вы хотите присоединить обработчик события к документу и позволить событию создать пузырь в DOM. Затем проверьте свойство event.target
, чтобы убедиться, что он соответствует требуемым критериям (в этом случае просто id
элемента).
Edit:
@shabunc обнаружил довольно большую проблему с моим решением - события на дочерних элементах не будут обнаружены правильно. Один из способов исправить это - посмотреть на элементы предков, чтобы увидеть, есть ли у них указанный id
:
function live (eventType, elementId, cb) {
document.addEventListener(eventType, function (event) {
var el = event.target
, found;
while (el && !(found = el.id === elementId)) {
el = el.parentElement;
}
if (found) {
cb.call(el, event);
}
});
}
Ответ 2
В дополнение к сообщению Andrew и Binyamin, возможно, это вариант:
С этим вы можете использовать "nav.item a" в качестве селектора.
На основе кода Andrew.
function live (eventType, elementQuerySelector, cb) {
document.addEventListener(eventType, function (event) {
var qs = document.querySelectorAll(elementQuerySelector);
if (qs) {
var el = event.target, index = -1;
while (el && ((index = Array.prototype.indexOf.call(qs, el)) === -1)) {
el = el.parentElement;
}
if (index > -1) {
cb.call(el, event);
}
}
});
}
live('click', 'nav .aap a', function(event) { console.log(event); alert('clicked'); });
Ответ 3
Альтернативой привязке события к динамическому отношению к определенному элементу может быть глобальный прослушиватель событий. Таким образом, каждый раз, когда вы обновляете DOM другим новым событием элемента на этом элементе, он также "улавливает". Пример:
var mybuttonlist = document.getElementById('mybuttonlist');
mybuttonlist.addEventListener('click', e=>{
if(e.target.nodeName == 'BUTTON'){
switch(e.target.name){
case 'createnewbutton':
mybuttonlist.innerHTML += '<li><button name="createnewbutton">Create new button</button></li>';
break;
}
}
}, false);
ul {
list-style: none;
padding: 0;
margin: 0;
}
<ul id="mybuttonlist">
<li><button name="createnewbutton">Create new button</button></li>
</ul>
Ответ 4
Другие решения немного сложнее...
document.addEventListener('click', e => {
if (e.target.closest('.element')) {
// .element has been clicked
}
}
Есть полифилл на случай, если вам понадобится поддержка Internet Explorer или старых браузеров.