addEventListener()

Содержание

Метод addEventListener - это самый функциональный способ позволяющий добавить обработчик события к указанному элементу и запустить выполнение программы при совершении заданного действия. Получить информацию о сигналах браузера можно из Document (DOM), Element, Window и других объектов поддерживающих события.

addEventListener() является одних из трёх способом прослушивать события, наряду с добавление атрибута к тегам в HTML и обращения к свойствам объекта напрямую.

    
    <!-- добавление атрибута -->
    <button onclick="alert('Терпение и труд всё перетрут')">Хочу стать программистом!</button>  
        
    <script>
        const myFirstEvent = document.querySelector('button');
        
        // обращаемся к свойству напрямую
        myFirstEvent.onclick = function() {     
            alert('Да будет так!');
        }
        
        // используем метод addEventListener
        myFirstEvent.addEventListener('click', function() {
            alert('Дорогу осилит идущий');
        })
    </script>   
    

addEventListener() имеет важное преимущество перед остальными способами, метод позволяет навесить несколько обработчиков на одно событие. Это происходит из-за того, что у объекта только одно свойство, например с именем onclick (клик) или mousemove (движение мыши) и если обратиться к одному из них напрямую несколько раз, второй обработчик перезапишет первый.

В примере выше, как раз можно наблюдать описанный эффект - модальное окно с Да будет так! появится, а вот Терпение и труд всё перетрут нет.

Также отследить некоторые события можно только с помощью addEventListener(), например навесить обработчик на DOMContentLoaded по другому не получиться.

Синтаксис

    
    element.addEventListener(eventType, handler, options);
    

element - объект, действие по которому отслеживаем.

eventType - тип события, которое мы хотим отследить: клик, прокрутка мыши, нажатие клавиши и т.д. Написание чувствительно к регистру: click правильно, Click или CLICK неправильно.

handler - имя функции или сама функция, которая будет выполнена после наступления события.

options - необязательный объект со свойствами, внутри которого доступны следующие параметры:

    
    <button>В скором времени я стану JavaScript middle</button>

    <script>
        const clickButton = document.querySelector('button');
        clickButton.addEventListener('click', showMessage, {
            capture: false,
            once: true,
            passive: false,
        })
        
        function showMessage() {
            alert('У тебя все получиться, я в тебя верю!');
        }
    </script>
    

При клике на кнопку мы получим модальное окно с сообщением, если кликнуть второй раз ничего не произойдет, так как свойство once равно true - после события обработчик удаляется.

removeEventListener()

Удалить обработчик события можно также с помощью метода removeEventListener(). В этом случае появляется возможность сделать это когда нам удобно. Для того, чтобы все сработало, первые два параметра у обоих методов должны быть идентичными. Важно также передать в removeEventListener() именно название функции, с анонимными функциями ничего не получиться, даже если записать код точь в точь.

    
    <button>Удалить обработчик события</button>

    <script>
        const clickButton = document.querySelector('button');
        clickButton.addEventListener('click', showMessage);
        
        function showMessage() {
            if (clickButton.innerText === 'Удалить обработчик события') {
                alert('Обработчик удален');
                clickButton.removeEventListener('click', showMessage);
            } else {
                alert('Обработчик не удален');
            }
        }
    </script>
    

В этом случае, если поменять текст на кнопке обработчик удален не будет.

Объект события

Для более детального представления о том какие действия происходят на странице используют объект события, который создается браузером после совершения действия. Такой объект записывается в качестве первого аргумента функции обработчика, для названия принято использовать event. Это позволяет гибко настраивать отслеживание получая информацию о том какая клавиша была нажата, координаты указателя мыши и другое.

    
    <button class="btn">JavaScript</button>

    <script>
        const btnJS = document.querySelector('.btn');
        btnJS.addEventListener('click', showElemObjEvent);
        
    function showElemObjEvent(event) {
        console.log(event.type); // тип события
        console.log(event.target); // элемент на котором произошло событие
        console.log(event.clientX); // координаты курсора по оси X
        console.log(event.clientY); // координаты курсора по оси Y
        console.log(event); // получим весь объект с информацией о событии
    }
    </script>
    

Популярные события

Рассмотрим события, которые отслеживаются чаще других:

click - клик левой кнопкой мыши по элементу, на сенсорных устройствах это касание;

contextmenu - клик на элемент правой кнопкой мыши - вызов контекстного меню;

mouseover / mouseout - наведение на элемент курсора мыши / курсор покидает элемент;

mousemove - движение мыши;

keydown / keyup - клавиша нажата / клавиша отпущена;

DOMContentLoaded - весь HTML загружен, а DOM-дерево построено.

Для того, чтобы посмотреть все возможные события для DOM-элемента, нажмите правой кнопкой на страницу, далее Просмотреть код, выберите элемент на странице, а далее кликните на Свойства (Properties). В фильтре наберите on, все что начинает на on являются событиями.

свойства элемента в браузере

Как добавить обработчик на множество элементом

addEventListener и forEach

    
    <button class="myChoice">JavaScript</button>
    <button class="myChoice">Python</button>
        
    <script>
        const choice = document.querySelectorAll('.myChoice');
        
        choice.forEach(choiceItem => {
            choiceItem.addEventListener('click', () => answer(choiceItem.innerHTML));
        })
        
        function answer(text) {
            if (text === 'JavaScript') {
                alert('Отличный выбор!');
            } else {
                alert('Возможно вы ошиблись?');
            }
        }
    </script>
    

В данном примере мы получили все элементы с классом myChoice в объект через querySelectorAll(), а потом с помощью forEach() перебором назначили обработчик события на все кнопки.

Делегирование событий

Вторым и более удачным способом отслеживать события на множестве элементов это делегирование.

    
    <style>
    td {
        border: 1px solid;
        width: 90px;
        height: 90px;
        text-align: center;
        border-color: black;
    }
    
    .hideText {
        color: white;
    }
    </style>
    
    <table>
        <td class="hideText">JavaScript</td>
        <td class="hideText">React</td>
        <td class="hideText">HTML</td>
    </table>
    
    <script>
    const getTable = document.querySelector('table');
    
    getTable.addEventListener('click', function(event) {
        if (event.target.closest('.hideText')) {
            event.target.classList.remove('hideText');
        }
    })
    </script>      
    

В этом примере мы назначаем обработчик для родителя в котором содержатся интересующие нас элементы. Далее отслеживаем с помощью event.target.closest('.hideText') было ли взаимодействие с тегом с классом .hideText и если это так удаляем оттуда класс, который делает текст белым.

Всплытие и погружение

Всплытие - это когда обработчик сначала срабатывает на элементе с которым произошло взаимодействие, затем событие обрабатывается на его родителе и далее выше по цепочке.

    
    <body> в четвертую очередь
        <span></span> не сработает
        <span> в третью очередь
            <span> во вторую очередь
                <span></span> кликаем сюда - обработчик сработает на этом элементе в первую очередь
            </span>
        </span>
    </body>
    

Погружение - при взаимодействии с объектом, который находится ниже чем элемент со свойством capture: true, сначала событие будет обработано на последнем, далее обработчик сработает на всех потомках и только потом на всех родителях.

    
    <body> в пятую очередь
        <span></span> не сработает
        <span> в четвертую очередь
          <span> - элемент со свойством capture: true - в первую очередь
            <span> - в третью очередь
              <span></span> кликаем сюда - обработчик сработает на этом элементе во вторую очередь
            </span>
          </span>
        </span>
     </body>
    

Для того, чтобы понять тему потренируйтесь на примере, наблюдая последовательность выполнения действий при клике на различные элементы. Результат отслеживайте в console.

Пример с квадратами
    
    <style>
    .square1 {
        width: 600px;
        height: 600px;
        background: red;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    
    .square2 {
        width: 450px;
        height: 450px;
        background: blue;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    
    .square3 {
        width: 350px;
        height: 350px;
        background: yellow;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    
    .square4 {
        width: 250px;
        height: 250px;
        background: white;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    </style>
    
    <div class="square1">
        <div class="square2">
            <div class="square3">
                <div class="square4"></div>
            </div>
        </div>
    </div>
    
    
    <script>
        const squareFirst = document.querySelector('.square1');
        const squareSecond = document.querySelector('.square2');
        const squareThird = document.querySelector('.square3');
        const squareFourth = document.querySelector('.square4');
        
        squareFirst.addEventListener('click', () => clickSquare('Квадрат №1'));
        squareSecond.addEventListener('click', () => clickSquare('Квадрат №2'));
        squareThird.addEventListener('click', () => clickSquare('Квадрат №3'), { "capture": true });
        squareFourth.addEventListener('click', () => clickSquare('Квадрат №4'));
        
        function clickSquare(text) {
            console.log(text);
        }
    </script>
    

Получаем доступ к элементу через this

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

    
    <button class="btn">После того, как выучу JS примусь за React</button>

    <script>
        const getButton = document.querySelector('.btn');
        getButton.addEventListener('click', printBtnText);
        
        function printBtnText() {
            alert(this.innerHTML);
        }
    </script>
    

Итого

Обработчик события это важный элемент в JavaScript, именно с помощью него можно отслеживать действия пользователя на странице. В свою очередь метод addEventListener() является основным способом для назначения таких обработчиков объектам.

Удалить обработчик события после использования можно двумя способами: с помощью свойства once со значением true или метода removeEventListener().

Для того, чтобы получить более подробную информацию о событии используют объект события, который передается первым аргументом в функцию. Отсюда можно получить координаты клика, какая кнопка была нажата и многое другое.

Для того, чтобы назначить обработчик множеству элементов используют принцип делегирования - событие фиксируется не только на элементе которому был назначен обработчик, но и на всех вложенных. Второй способ - это навешивание обработчиков через цикл forEach().