Реализация jQuery "живого" связующего с нативным Javascript - PullRequest
26 голосов
/ 02 февраля 2012

Я пытаюсь выяснить, как связать событие с динамически создаваемыми элементами.Мне нужно, чтобы событие сохранялось на элементе даже после того, как он был уничтожен и регенерирован.

Очевидно, что с живой функцией jQuery это легко, но как бы они выглядели, реализованными с помощью собственного Javascript?

Ответы [ 4 ]

22 голосов
/ 02 февраля 2012

Вот простой пример:

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);
        }
    });
}
18 голосов
/ 02 августа 2014

В дополнение к сообщению Эндрю и комментарию Биньямина, возможно, это вариант:

При этом вы можете использовать «nav .item a» в качестве селектора. На основании кода Андрея.

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'); });
1 голос
/ 01 февраля 2019

Другие решения немного сложнее ...

document.addEventListener('click', e => {
   if (e.target.closest('.element')) {
       // .element has been clicked
   }
}

Существует polyfill на случай, если вам потребуется поддержка Internet Explorer или старых браузеров.

1 голос
/ 19 января 2018

Альтернативой динамическому привязыванию события к определенному элементу может быть глобальный прослушиватель событий. Таким образом, каждый раз, когда вы обновляете 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>

В этом примере у меня есть прослушиватель событий на <ul> для событий щелчка. Итак, событие происходит для всех дочерних элементов. Из простого обработчика событий, который я создал, вы можете легко добавить больше логики, больше кнопок (с разными или повторяющимися именами), привязок и т. Д.

Если пойти ва-банк, вы можете добавить в документ список событий вместо элемента списка, перехватывая все события щелчка на странице, а затем обрабатывать события щелчка в обработчике событий.

...