addEventListener()

Содержание

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

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

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

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

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

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

Синтаксис

    element.addEventListener(eventType, handler, options);

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

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

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

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

  • capture: значение записывается в формате true или false и задает этап, на котором будет обработано событие. По умолчанию false - на этапе всплытия, true - на этапе погружения (перехват). Если вместо options задать булево значение - это будет равносильно {capture: false/true}
  • once: значение типа boolean, по умолчанию false, если true тогда обработчик будет удален после выполнения.
  • passive: по умолчанию false, если true обработчик никогда не вызовет preventDefault(), взамен этого будет сгенерировано предупреждение в console.
    <button>В скором времени я стану JavaScript middle</button>

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

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

removeEventListener()

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

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

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

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

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

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

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

    <script>{"const btnJS = document.querySelector('.btn');\n        btnJS.addEventListener('click', showElemObjEvent);\n        \n    function showElemObjEvent(event) {\n        console.log(event.type); // тип события\n        console.log(event.target); // элемент на котором произошло событие\n        console.log(event.clientX); // координаты курсора по оси X\n        console.log(event.clientY); // координаты курсора по оси Y\n        console.log(event); // получим весь объект с информацией о событии\n    }"}</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');\n        \n        choice.forEach(choiceItem => {\n            choiceItem.addEventListener('click', () => answer(choiceItem.innerHTML));\n        })\n        \n        function answer(text) {\n            if (text === 'JavaScript') {\n                alert('Отличный выбор!');\n            } else {\n                alert('Возможно вы ошиблись?');\n            }\n        }"}</script>

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

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

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

    <style>{"td {\n        border: 1px solid;\n        width: 90px;\n        height: 90px;\n        text-align: center;\n        border-color: black;\n    }\n    \n    .hideText {\n        color: white;\n    }"}</style>
    
    <table>
        <td class="hideText">JavaScript</td>
        <td class="hideText">React</td>
        <td class="hideText">HTML</td>
    </table>
    
    <script>{"const getTable = document.querySelector('table');\n    \n    getTable.addEventListener('click', function(event) {\n        if (event.target.closest('.hideText')) {\n            event.target.classList.remove('hideText');\n        }\n    })"}</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 {\n        width: 600px;\n        height: 600px;\n        background: red;\n        display: flex;\n        justify-content: center;\n        align-items: center;\n    }\n    \n    .square2 {\n        width: 450px;\n        height: 450px;\n        background: blue;\n        display: flex;\n        justify-content: center;\n        align-items: center;\n    }\n    \n    .square3 {\n        width: 350px;\n        height: 350px;\n        background: yellow;\n        display: flex;\n        justify-content: center;\n        align-items: center;\n    }\n    \n    .square4 {\n        width: 250px;\n        height: 250px;\n        background: white;\n        display: flex;\n        justify-content: center;\n        align-items: center;\n    }"}</style>
    
    <div class="square1">
        <div class="square2">
            <div class="square3">
                <div class="square4"></div>
            </div>
        </div>
    </div>
    
    
    <script>{"const squareFirst = document.querySelector('.square1');\n        const squareSecond = document.querySelector('.square2');\n        const squareThird = document.querySelector('.square3');\n        const squareFourth = document.querySelector('.square4');\n        \n        squareFirst.addEventListener('click', () => clickSquare('Квадрат №1'));\n        squareSecond.addEventListener('click', () => clickSquare('Квадрат №2'));\n        squareThird.addEventListener('click', () => clickSquare('Квадрат №3'), { \"capture\": true });\n        squareFourth.addEventListener('click', () => clickSquare('Квадрат №4'));\n        \n        function clickSquare(text) {\n            console.log(text);\n        }"}</script>

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

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

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

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

Итого

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

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

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

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