логотип PurpleSchool
  • Бесплатно
    • Курсы
    • JavaScript Основы разработкиPython Основы PythonCSS CSS FlexboxКарта развития
    • База знанийИконка стрелки
    • Новостные рассылкиИконка стрелки
  • Карьерные пути
    • Frontend React разработчик
    • Frontend Vue разработчик
    • Backend разработчик Node.js
    • Fullstack разработчик React / Node.js
    • Mobile разработчик React Native
    • Backend разработчик Golang
    • Devops инженер
  • О нас
    • Отзывы
    • Реферальная программа
    • О компании
    • Контакты
  • Иконка открытия меню
    • Сообщество
    • PurpleПлюс
    • AI тренажёр
    • Проекты
логотип PurpleSchool
ютуб иконка
Telegram иконка
VK иконка
VK иконка
Курсы
ГлавнаяКаталог курсовFrontendBackendFullstack
Практика
КарьераПроектыPurpleПлюс
Материалы
БлогБаза знаний
Документы
Договор офертаПолитика конфиденциальностиПроверка сертификатаМиграция курсовРеферальная программа
Реквизиты
ИП Ларичев Антон АндреевичИНН 773373765379contact@purpleschool.ru

PurpleSchool © 2020 -2026 Все права защищены

  • Курсы
    • FrontendИконка стрелки
    • BackendИконка стрелки
    • DevOpsИконка стрелки
    • MobileИконка стрелки
    • ТестированиеИконка стрелки
    • Soft-skillsИконка стрелки
    • ДизайнИконка стрелки
    Иконка слояПерейти в каталог курсов
  • логотип PurpleSchool
    • Сообщество
    • PurpleПлюс
    • AI тренажёр
    • Проекты
    Главная
    Сообщество
    Browser Events: Погружение в события браузера и всплытие с новыми знаниями

    Browser Events: Погружение в события браузера и всплытие с новыми знаниями

    Аватар автора Browser Events: Погружение в события браузера и всплытие с новыми знаниями

    Валерий Шестернин

    Иконка календаря09 августа 2023

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

    Виды событий

    Событие является уведомлением от браузера о совершении определенного действия или изменении состояния элемента веб-страницы. Их можно условно разделить на:

    • События устройств ввода (обычно клавиатура и мышь): "click", "mousedown" и "mouseup", позволяют обрабатывать клики, а "keydown", "keyup" и "keypress" - отслеживать ввод с клавиатуры.
    • События элементов управления(инпуты, формы и т.п.): "focus" и "blur" позволяют контролировать фокус, "change" - изменение элемента, “submit” - отправку формы.
    • События CSS: “aninationstart” - CSS-анимация началась, “transitionend" – CSS-переход завершен и т.д.
    • События документа: DOMContentLoaded – DOM готов, beforeunload – пользователь покидает страницу, load – внешние ресурсы загружены, стили применены и т.д.

    Если Вам необходимо получить информацию о конкретном событии и его описание, рекомендую обратиться к подробному справочнику на MDN (https://developer.mozilla.org/ru/docs/Web/Events). В данной статье мы разберем взаимодействие с событиями и начнем с трех вариантов их обработки.

    В HTML разметке

    Что бы обработать событие мы можем просто добавить нужному тегу специальный атрибут (названия таких атрибуты состоят из “on” и названия события, как onclick, onchange и т.д.) и передать в него функцию, которая должна сработать при активации события. Вместо функции можно передать код, который так же исполнится при активации события, но такое описание чувствительно к формату скобок и сработает только если сам код будет обернут в двойные скобки(”код”), а строки в нем в одинарные(’строка’):

        <script type="text/javascript">
            const toThank = () =>{console.log('Thanks!')}
        </script>
        <button onclick="console.log('Thanks!')">Click me</button>
        <button onclick="toTank()">Click me</button> 
        //эти две строки кода отработают идетично
        <button onclick="console.log("Thanks!")">Click me</button> 
        //а здесь будет ошибка из-за неправельных скобок
    

    Через DOM-свойство

    Обработчик, который мы создали в предыдущем примере, будет храниться в свойстве DOM-объекта. Мы можем обратиться к такому свойству чтобы создать обработчик, а название такого свойства совпадает с названием атрибута и чувствительно к регистру:

        <button id="myButton">Click me</button>
        <script type="text/javascript">
            const button = document.getElementById("myButton");
            button.onclick = () =>  console.log("Thanks!");
        </script>
    

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

        <button id="myButton">Click me</button>
        <script type="text/javascript">
            const toThank = () =>{console.log('Thanks!')}
            const button = document.getElementById("myButton");
            button.onclick = toThank();
            //не сработает потому что функция сразу вызывается
            button.setAttribute('onclick', toThank);
            //тоже не будет работать потому что превратится в строку
        </script>
    

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

        <button onclick="console.log('Thanks!')" id="myButton">Click me</button>
        <script type="text/javascript">
            const button = document.getElementById("myButton");
            button.onclick = () => {return false}
            //так мы назначим новый обработчик и отменим действие
        </script>
        <a href="/" onclick="return false">Click me</a>
        <a href="/" onclick="event.preventDefault()">Click me</a>
        //а в этих двух примерах - отменили действие по умолчанию 
        //теперь ссылка не откроется при нажатии 
    

    С помощью метода addEventListener

    Оба предыдущий способа имеют серьезный недостаток - нельзя повесить несколько обработчиков на одно событие. Для таких случаев есть специальный метод addEventListener который принимает название события, функцию и необязательные параметры настроек: element.addEventListener(event, handler, [options]);. В настройках есть следующие опции: once:true означает что после срабатывания обработчик будет удален, passive:true сообщает браузеру что слушатель не будет отменять действие по умолчанию и capture к которому мы вернемся немного позже.

        <button id="myButton">Click me</button>
        <script type="text/javascript">
          const button = document.getElementById("myButton");
          const handler1 = () => {console.log('Thanks!')}
          const handler2 = () => {console.log('Thanks again!')}
    
          button.onclick = () => {console.log('Hi!')};
          button.addEventListener('click', handler1);
          button.addEventListener('click', handler2);
        </script>
    

    Существуют события, которые могут быть обработаны только с использованием метода addEventListener. Одним из них является DOMContentLoaded, которое возникает, когда загрузка и построение DOM документа завершены.

    В отличии от объявления в разметке или через DOM-свойство, не предусмотрено возможности получить обработчики созданные с помощью addEventListener из элемента. Поэтому существует метод removeEventListener который принимает строго те же параметры что и addEventListener, с помощью которого был добавлен слушатель. Важно заметить что, если при создании слушателя функция была описана в нем, а не объявлена в другой части кода, такой слушатель невозможно удалить:

        button.addEventListener("click", () => {console.log("Thanks")});
        button.removeEventListener("click", () => {console.log("Thanks")});
        //не сработает т.к. это две разные функции
        const toTank = () => {console.log("Thanks")};
        button.addEventListener("click", toTank);
        button.removeEventListener("click", toTank);
        //здесь передана одна и та же функция и все сработает
    

    Жизненный цикл события (погружение и всплытие)

    В примерах ранее мы рассматривали довольно простые случаи с нажатием на единичные кнопки и ссылки, а если их много и мы должны отслеживать их все? Или если мы повесим слушатель на элемент, а пользователь нажмет на вложенный, у которого нет слушателя? Придется вешать слушатели на каждый? На самом деле нет потому что почти все события в браузере проходят три фазы: погружение (capturing), фаза цели (target phase) и всплытие (bubbling stage). С их помощью мы можем поймать событие, даже если на целевом элементе (тот на котором произошло событие) нет слушателя.

    В основном используется фаза всплытия. Во время этой фазы событие, при наличии обработчика, сначала активирует его на целевом элементе, затем на родителе и так на всех родительских элементах по цепочке. При этом мы можем узнать целевой элемент события с помощью метод target объекта события, который как аргумент принимает вызываемая функция.

    <div id="myDiv">
      <button id="button-1">Click me</button>
      <button id="button-2">Click me too</button>
    </div>
    <script type="text/javascript">
      const sayHi = (event) => {
        setTimeout(() => {
          console.log(`Hello I am div, but the target is ${event.target.id}!`);
        }, 0);
      };
      const element = document.getElementById("myDiv");
      element.addEventListener("click", sayHi);
    </script>
    //Несмотря на то что на кнопках нет обработчиков 
    //собитие нажатия на них всплывет до div и он поздаровается
    //сообщив id нажатой кнопки
    

    Всплытие можно остановить вызвав метод event.stopPropagation() на последнем элементе, обработчик которого нужно запустить или event.stopImmediatePropagation() что бы кроме остановки всплытия предотвратить и срабатывание обработчика.

    Вернемся к остальным фазам жизненного цикла события. Фазу цели нельзя обработать отдельно, а для обработки погружения нужно при объявлении обработчика через addEventListener передать опциональным параметром {capture: true} или просто true, если другие опции слушателя не заданы. Как уже понятно из названия, погружение аналогично всплытию, но в этой фазе событие опускается по цепочке вложенных элементов к целевому.

    <div>
      <button >Click me</button>
    </div>
    <script type="text/javascript">
        //веваем слушателей на все элементы страницы
      for(let element of document.querySelectorAll('*')) {
        element.addEventLstener("click", e => console.log(element.tagName), true);
      }
    </script>
    //В консоль будут выведены все теги по цепочке до нашей кнопки:
    //HTML
    //BODY
    //DIV
    //BUTTON
    

    Выше я упомянул что не все события проходят фазы жизненного цикла. Например события focus и blur относятся только к элементу на котором установлен или снят фокус, submit - только к отправляемся форме, а load к загруженному ресурсу или странице поэтому они не погружается и не всплывают, но это скорее исключения, потому что большинство событий проходят все фазы.

    Заключение

    Браузерные события являются важной составляющей веб-разработки, предоставляя возможность создавать отзывчивые пользовательские интерфейсы. Надеюсь что данная статья была полезна для понимания такой важной темы.

    Иконка глаза3 674

    Комментарии

    0

    Постройте личный план изучения Основы разработки до уровня Middle — бесплатно!

    Основы разработки — часть карты развития Frontend, Backend, Mobile

    • step100+ шагов развития
    • lessons30 бесплатных лекций
    • lessons300 бонусных рублей на счет

    Бесплатные лекции

    Лучшие курсы по теме

    изображение курса

    Основы Git

    Антон Ларичев
    AI-тренажеры
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    HTML и CSS

    Антон Ларичев
    AI-тренажеры
    Практика в студии
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    3 999 ₽ 6 990 ₽
    Подробнее
    изображение курса

    CSS Flexbox

    Антон Ларичев
    Гарантия
    Бонусы
    иконка звёздочки рейтинга4.9
    бесплатно
    Подробнее
    Иконка чипа0