Всплытие и перехват событий

Всплытие и перехват событий

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

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

Этот обработчик для <div> сработает, если вы кликните по вложенному тегу <em> или <code>:

<div onclick="alert('Обработчик на Div сработал!')">
  <em>Кликните на EM, сработает обработчик на DIV</em>
</div>

Как видите при клике на вложенном элементе em срабатывает обработчик на div. Почему так происходит? Читайте дальше и узнаете.

Всплытие событий javascript

Всплытие

Итак основной принцип всплытия:

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

Например, пусть имеется   3 вложенных элемента FORM > DIV > P, с обработчиком  собьытия на каждом:

<style>
  body * {
    margin: 10px;
    border: 1px solid blue;
  }
</style>

<form onclick="alert('form')">FORM
  <div onclick="alert('div')">DIV
    <p onclick="alert('p')">P</p>
  </div>
</form>

Просмотреть  пример

Всплытие гарантирует, что клик по внутреннему  элементу <p> вызовет обработчик click (если  он конечно есть) сначала на самом <p>, а затем на элементе <div> и  далее на элементе <form>, и так далее вверх по цепочке родителей до самого главного родителя document.

Такой процесс называется всплытием, потому что события  как бы «всплывают» от внутреннего элемента вверх через своих  родителей, подобно тому, как всплывает пузырек воздуха в воде, поэтому можно встретить еще определение бабблинг ну это просто  от английского слова bubbling — всплывать.

Читайте также  Введение в события JavaScript

Следует отметить, что всплывают почти все события. Например событие focus не всплывает.

Доступ к целевому элементу event.target

Для того, чтобы узнать на каком именно элементе мы поймали то или иное событие и существует метод event.target. (о объекте event читайте здесь).

Этот метод отличается от this:

  • event.target – это собственно исходный элемент, на котором и произошло событие.
  • this – это всегда текущий элемент, до которого дошло всплытие, и на нём сейчас выполняется обработчик.

Например, если у вас установлен  только один обработчик form.onclick, то он и  «поймает» все клики внутри формы.  При этом где бы ни был клик внутри – он все равно  всплывёт до элемента <form>, на котором и  сработает  уже обработчик.

При этом:

  • this (=event.currentTarget) всегда будет сама форма, так как обработчик сработал  именно на ней.
  • event.target будет содержать ссылку на конкретный элемент внутри формы, самый вложенный, на котором произошёл клик.

В принципе this может совпадать с event.target если кликнули по форме и в форме больше нет  никаких элементов.

Прекращение всплытия

Как правило всплытие события идет прямо наверх и доходит до корневого объекта window.

Но есть возможность остановить всплытие на каком-то промежуточном элементе.

Для того, чтобы остановить  всплытие надо вызвать метод event.stopPropagation().

Рассмотрим пример, при клике на кнопку обработчик body.onclick не сработает:

<body onclick="alert('сюда обработка не дойдёт')">
  <button onclick="event.stopPropagation()">Кликни меня</button>
</body>

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

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

Читайте также  События мыши: mouseover/out, mouseenter/leave

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

Погружение

В стандарте, кроме «всплытия» событий, есть ещё и «погружение».

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

Итак имеются 3 стадии прохода события:

  1. Событие идет сверху вниз. Эта стадия называется «стадия перехвата».
  2. Событие достигло конкретного элемента. Это – «стадия цели».
  3. После всего событие начинает всплывать. Это – «стадия всплытия».

В стандарте это продемонстрировано так:

погружение события JavaScript

 

Таким образомь, при клике на TD событие  будет путешествовать по цепочке родителей сначала вниз к элементу («погружается»), а потом наверх («всплывает»), по пути соотвественно задействуя обработчики.

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

Обработчики ничего не знают о стадии перехвата, а начинают работать со всплытия.

А Чтобы поймать событие на стадии перехвата, как раз и нужно использовать третий аргумент addEventListener :

  • Аргумент true, то событие будет перехвачено по дороге вниз.
  • Аргумент false, то событие будет поймано при всплытии.

Примеры

В примере на <form>, <div>, <p> стоят те же обработчики, что и раньше, но на сей раз – на стадии погружения.  Ну а чтобы увидеть перехват в действии, кликните в нём на элементе <p>:

Обработчики сработают в порядке «сверху-вниз»: FORM → DIV → P.

JS-код здесь такой:

var elems = document.querySelectorAll('form,div,p');

// на каждый элемент повесим обработчик на стадии перехвата
for (var i = 0; i < elems.length; i++) {
  elems[i].addEventListener("click", highlightThis, true);
}

Просмотреть пример
Никто вам не мешает назначить обработчики для обеих стадий, вот так:

var elems = document.querySelectorAll('form,div,p');

for (var i = 0; i < elems.length; i++) {
  elems[i].addEventListener("click", highlightThis, true);
  elems[i].addEventListener("click", highlightThis, false);
}

Кликните по внутреннему элементу <p>, чтобы увидеть порядок прохода события:
Должно быть FORM → DIV → P → P → DIV → FORM. Заметим, что элемент <p> будет участвовать в обоих стадиях.

Читайте также  Прокрутка документа: событие scroll

Итоги

  • При наступлении события – элемент, на котором  произошло событие, помечается как event.target.
  • Событие сначала двигается вниз от корня документа к event.target, по пути вызывая обработчики, поставленные через addEventListener(…., true).
  • Событие двигается от event.target вверх до начала документа, по пути оно вызывает обработчики, поставленные через  addEventListener(…., false).

Каждый обработчик будет иметь доступ к свойствам события:

  • event.target – самый глубокий элемент, на котором  собственно и произошло событие.
  • event.currentTarget (=this) – элемент, на котором в данный момент сработал  самобработчик (до которого «дошло» событие).
  • event.eventPhase – на какой фазе  сработал  обработчик события (погружение =1, всплытие = 3).

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

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Плюсануть
Поделиться

Об авторе

admin administrator

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: