Методы event.preventDefault() и event.stopPropagation()

frontend logo

Хочешь проверить свои знания по фронтенду?

Подпишись на наш канал с тестами по HTML/CSS/JS в Telegram!

Решать задачи

×

Методы event.preventDefault() и event.stopPropagation()

Браузеры имеют установленные по умолчанию варианты поведения в различных случаях.

Например, когда пользователь нажимает кнопку «Отправить», по умолчанию форма отправляется к указанному обработчику.

А при клике по потомку элемента событие клика также затрагивает сам элемент, потому что это главный контейнер.

В некоторых случаях вам может понадобиться перекрыть эти установки по умолчанию. В этой статье мы познакомимся с методами event.preventDefault() и event.stopPropagation(). С их помощью мы будем отменять некоторые дефолтные действия браузера.

event.preventDefault()

Этот метод предотвращает дефолтные действия, предпринимаемые браузером при запуске события.

Давайте рассмотрим несколько примеров таких действий, установленных по умолчанию, и способы их предотвращения при помощи event.preventDefault().

Как отменить дефолтную отправку формы

Когда пользователь отправляет форму (нажимает кнопку «Отправить»), действие по умолчанию для формы — отправка данных на URL, где данные будут обработаны.

Элементы формы имеют атрибуты action и method, которые указывают URL, по которому отсылаются данные, и тип запроса (get, post и т. п.).

Если эти атрибуты не переданы, по умолчанию в качестве URL будет использоваться текущий URL, по которому была отправлена форма. В качестве метода по умолчанию используется get.

Например, этот код:

<form>
  <input name="email" />
  <input name="password" />
  <input type="submit" />
</form>

даст такой результат:

Методы event.preventDefault() и event.stopPropagation()

При отправке формы с входными данными «dillion» и «password» вы увидите, что запрос get отправлен по адресу 127.0.0.1:5500/index.html:

Методы event.preventDefault() и event.stopPropagation()

Так браузеры обрабатывают формы по умолчанию.

Но с данными можно много всего сделать до отсылки запроса. Современный подход к работе с формами вообще предполагает такие дополнительные действия.

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

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

Делается это так:

<form id='form'>
  ...
</form>
const form = document.getElementById('form')

form.addEventListener('submit', (event) => {
  event.preventDefault()
  
  // process data and submit a request manually
})

Теперь отправка формы в ваших руках.

От редакции Techrocks. Предлагаем также почитать другие статьи о создании форм:

Как отменить действие по умолчанию для клика по ссылке

Когда вы кликаете по ссылке (тег a с атрибутом href), действие по умолчанию — переход по этой ссылке.

Но что, если вы хотите сделать что-то перед переходом? Например, проверить, есть ли доступ у пользователя к той странице, на которую он хочет перейти. Вот как это сделать:

<a id="link" href="https://google.com">Google</a>
const link = document.getElementById("link")

link.addEventListener("click", event => {
  event.preventDefault()

  // сделать что-то и перейти
})

Теперь при клике на ссылку «Google» переход по ссылке не происходит автоматически. Вы отменили действие перехода, установленное по умолчанию, и вам придется управлять им самостоятельно.

event.stopPropagation()

Propagation — это распространение событий. Метод stopPropagation используется для предотвращения распространения (всплытия) событий, когда событие запускается на отдельном элементе.

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

Чтобы в этом разобраться, используем пример.

Клик на потомке элемента

Допустим, у вас есть следующие элементы:

<div>
  <button>Click me</button>
</div>

Когда вы кликаете на button, вы также кликаете по контейнеру div, потому что button находится в этом контейнере. Эта логика означает, что событие клика всплывает от кнопки к контейнеру. На этом событие не останавливается, оно продолжает всплывать к более далеким предкам, пока не достигнет корня.

Чтобы это проверить, рассмотрим код:

<div id="div">
  <button id="button">Click me</button>
</div>
const div = document.getElementById('div')
const button = document.getElementById('button')

button.addEventListener('click', () => {
  console.log('button clicked')
})

div.addEventListener('click', () => {
  console.log('div container clicked')
})

Если вы запустите этот код в браузере и нажмете на кнопку, вы получите следующий результат:

Методы event.preventDefault() и event.stopPropagation()

Контейнер div тоже получает событие click.

Всплытие событий — поведение браузера по умолчанию. Но в некоторых случаях вам может потребоваться другое поведение.

Рассмотрим пример.

Вот всплывающее окно нового сообщения в Gmail:

Методы event.preventDefault() и event.stopPropagation()

Вверху у вас три кнопки для различных действий. Одна сворачивает окно, вторая раскрывает его на весь экран, а третья закрывает.

Но верхняя панель с текстом «New Message» тоже имеет обработчик событий. Если по ней кликнуть, окно сворачивается:

Методы event.preventDefault() и event.stopPropagation()

Кликая на любую из кнопок, вы не хотите, чтобы событие клика распространялось на верхнюю панель и при этом выполнялась функция для этого события. То есть, кликая на кнопку «Закрыть», вы не хотите, чтобы верхняя панель сворачивалась.

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

Предположим, наше всплывающее окно построено следующим образом:

<div id='top-bar'>
  <!-- The Message Element -->
  <!-- The Buttons -->
</div>
const topBar = document.getElementById('top-bar')
const closeButton = document.getElementById('close-btn')

topBar.addEventListener('click', () => {
  // minimize or maximize popup
})

closeButton.addEventListener('click', () => {
  // close popup
})

Чтобы предотвратить всплытие события к верхней панели, вам нужно добавить метод stopPropagation для слушателя событий button. Выглядит это так:

closeButton.addEventListener('click', (event) => {
  event.stopPropagation()
  // close popup
})

Таким образом верхняя панель будет получать событие click, только если кликнут непосредственно по ней.

От редакции Techrocks. Возможно, вас также заинтересует статья «Как создать ссылку mailto в HTML».

Итоги

Мы познакомились с методами event.preventDefault() и event.stopPropagation(). Первый предотвращает действия браузера, установленные по умолчанию, а второй — дефолтное поведение событий — распространение вверх по дереву.

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

Перевод статьи «How to Manage Browser Defaults with event.preventDefault() and event.stopPropagation()».

Запись Методы event.preventDefault() и event.stopPropagation() впервые появилась Techrocks.