Это сообщение изначально было опубликовано на webinuse.com

При работе с JavaScript и DOM нам часто приходится динамически создавать некоторые элементы. Особенно при работе с некоторыми таблицами и выборке данных с сервера. Иногда нам приходится привязывать события к динамически создаваемым элементам. И это именно то, что мы собираемся сделать сейчас.

Когда jQuery использовался (он все еще используется сегодня, но не так часто, как раньше), мы просто прикрепляли событие к body, а затем присоединяли его к элементу. По сути, jQuery найдет для нас этот элемент в дереве DOM и запустит нужную функцию. Давайте посмотрим пример.

$("body").on("click", "dynamic-element", function(){});

В приведенном выше примере jQuery будет прикреплять события к динамически создаваемым элементам или любым элементам, если на то пошло, которые мы передали в качестве параметра.

Привязывайте события к динамически создаваемым элементам с помощью всплывающей подсказки.

Первый способ, который мы собираемся попробовать, — это привязывать события к динамически создаваемым элементам, используя метод всплытия. Что это значит? Это означает, что мы будем нацеливаться на родителя, а не на фактический элемент. А затем мы собираемся проверить, щелкнул ли пользователь по элементу или где-то еще.

<div id="container">
    <button class="click-btn">The First Button</button>
</div>
<script>
    /**
     * First, we select parent element
     * */
    const container = document.querySelector("#container");
    /**
     * After that we add event listener to that element
     * */
    container.addEventListener("click", function(e){
        /**
         * Then, we check if we clicked on an element that has
         * .click-btn class
         * */
        if (e.target.classList.contains('click-btn')) {
            /**
             * If we have clicked on such element we
             * run some function
             * */
          alert(`You have clicked ${e.target.innerHTML}`);
        }
    })
    /**
     * Now let's create our dynamic element
     * Another button
     * */
    const btn = document.createElement("button");
    /**
     * In order for event bubbling to work,
     * we have to add the same class as we used
     * in our eventListener
     * */
    btn.className = "click-btn";
    //Then we add some text inside that button
    btn.innerText = "The dynamically created button";
    //And we append it
    container.appendChild(btn);
</script>

Как мы видим в приведенном выше примере, мы добавили eventListener к родителю, но он будет работать, только если пользователь щелкнет элемент с классом click-btn.

После того, как мы это сделали, мы динамически создали еще одну кнопку с тем же классом. И по логике вещей, eventListener будет запускать на этой кнопке ту же функцию, что и на той, которую мы создали в HTML.

Как динамически привязывать события к динамически создаваемым элементам

Второй способ привязки событий к динамически создаваемым элементам — создание функции и запуск этой функции на созданных нами элементах. Звучит запутанно? Давайте создадим несколько примеров.

<div id="container">
    <button class="click-btn">The First Button</button>
</div>
<script>
/**
 * First let's create a function
 * */
function dynamicFunction(e) {
    e.preventDefault();
    alert(`You have clicked on ${e.target.innerHTML}`)
}
/**
 * Now let's create our dynamic element
 * */
//First we select our container
const container = document.querySelector("#container");
//Then, we create a button
const btn = document.createElement("button");
//Then, we add it the same as their respective siblings
btn.className = "click-btn";
//Now, we add it some text
btn.innerText = "The dynamically created button";
//Lastly, append it to the container
container.appendChild(btn);
/**
 * Since we are going to attach eventListener to a class
 * we need a loop
 * */
 //Let's store our elements to variable
 const elements = document.querySelectorAll(".click-btn");
 //Then, we loop through those elements
 for(let i = 0; i < elements.length; i++) {
     //We add eventListener to each element
     elements[i].addEventListener("click", dynamicFunction);
 }
</script>

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

Но есть одна загвоздка. Если бы мы создали нашу кнопку, скажем, после того, как мы сделали .fetch(), нам нужно было бы снова запустить цикл. Почему? Потому что новые элементы не были частью DOM, когда мы запускаем цикл в первый раз. Так что можно считать это недостатком.

Какой способ лучше?

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

Если у вас есть какие-либо вопросы или что-то еще, вы можете найти меня в моем Твиттере или вы можете прочитать некоторые из моих других статей, таких как Как просто преобразовать любой HTML-шаблон в тему WordPress менее чем за 10 минут?