Конспект JS-course


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

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

Это происходит потому, что событие всплывает.

Например, этот обработчик для DIV сработает, если вы кликните по вложенному тегу EM или CODE :

Всплытие

Основной принцип всплытия:

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

Например, есть 3 вложенных блока:

Всплытие гарантирует, что клик по внутреннему div 3 вызовет событие onclick сначала на внутреннем элементе 3, затем на элементе 2 и в конце концов на элементе 1.

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

Текущий элемент, this

Элемент, на котором сработал обработчик, доступен через this.

Например, повесим на клик по каждому DIV функцию highlight , которая подсвечивает текущий элемент:

Также существует свойство объекта события event.currentTarget .

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

IE8- при назначении обработчика через attachEvent не передаёт this . Браузеры IE8- не предоставляют this при назначении через attachEvent . Также в них нет свойства event.currentTarget .

Если вы будете использовать фреймворк для работы с событиями, то это не важно, так как он всё исправит. А при разработке на чистом JS имеет смысл вешать обработчики через onсобытие: это и кросс-браузерно, и this всегда есть.

Целевой элемент, event.target

Самый глубокий элемент, который вызывает событие, называется «целевым» или «исходным» элементом.

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

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

Всплытие идет прямо наверх. Обычно оно будет всплывать до <HTML> , а затем до document , вызывая все обработчики на своем пути.

Но любой промежуточный обработчик может решить, что событие полностью обработано, и остановить всплытие.

Сценарий, при котором это может быть нужно:

  1. На странице по правому клику показывается, при помощи JavaScript, специальное контекстное меню;
  2. На странице также есть таблица, которая показывает меню, но другое, своё;
  3. В случае правого клика по таблице её обработчик покажет меню и остановит всплытие, чтобы меню уровня страницы не показалось.

Код для остановки всплытия различается между IE

Стандартный код — это вызов метода:

Есть еще вариант записи в одну строчку:

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

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

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

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

Например, вы для одного компонента интерфейса сделали stopPropagation на событие click . А позже, на совсем другом месте страницы понадобилось отследить «клик вне элемента» — скажем, чтобы закрыть пункт меню. Обычно для этого ставят обработчик document.onclick и по event.target проверяют, внутри был клик или нет. Но над областью, где клики убиваются stopPropagation , такой способ будет нерабочим!

Три стадии прохода событий

Событие сначала идет сверху вниз. Эта стадия называется «стадия перехвата» (capturing stage). Событие достигло целевого элемента. Это — «стадия цели» (target stage). После этого событие начинает всплывать. Это — «стадия всплытия» (bubbling stage). Получается такая картина:

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

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

Стадия цели как-то особо не обрабатывается, но обработчики, назначаемые на стадии захвата и всплытия, срабатывают также на целевом элементе.

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

Чтобы назначить обработчики для обеих стадий, добавим новое событие: var divs = document.getElementsByTagName(‘div’);

Как видно из примера, один и тот же обработчик можно назначить на разные стадии. При этом номер текущей стадии он, при необходимости, может получить из свойства event.eventPhase .


Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *