DevGang
Авторизоваться

События JavaScript: всплытие, захват и распространение

События в JavaScript - это события, которые могут запускать определенную функциональность и приводить к определенному поведению. Распространенным примером события является «click» или «hover». Вы можете настроить прослушивателей для отслеживания этих событий, которые вызовут желаемую функциональность.

Что такое «распространение»?

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

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

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

Целевой объект - это узел DOM, на который вы нажимаете или запускаете любое другое событие.

Например, кнопка с событием щелчка будет целью события.

Корень - это родительский элемент самого высокого уровня целевого объекта. Обычно это документ, который является родительским элементом , который является (возможно, удаленным) родительским элементом вашего целевого элемента.

Захват используется не так часто, как всплытие, поэтому наши примеры будут вращаться вокруг фазы всплытия. Однако в качестве опции EventTarget.addEventListener() имеет необязательный третий параметр, который принимает аргумент в виде логического значения, который управляет фазой распространения. Параметр называется useCapture, и передача значения true приведет к тому, что прослушиватель будет находиться на этапе захвата. Значение по умолчанию — false, что применит его к фазе всплытия.

Как только вы инициируете событие, will _propagate _ up корня и вызовет каждый отдельный обработчик событий, связанный с одним и тем же типом. Например, если у вашей кнопки есть событие щелчка, во время фазы всплытия оно будет подниматься до корня и запускать каждое событие щелчка по пути.

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

Event.stopPropagation()

Эти два метода используются для решения ранее упомянутой проблемы, касающейся распространения событий. Вызов Event.stopPropagation() предотвратит дальнейшее распространение по дереву DOM и запустит только обработчик события, из которого оно было вызвано.

<!--Try it-->
function first() {
  console.log(1);
}
function second() {
  console.log(2);
}
let button = document.getElementById("button");
let container = document.getElementById("container");
button.addEventListener("click", first);
container.addEventListener("click", second);

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

function first(event) {
  event.stopPropagation();
  console.log(1);
}

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

Отличие Event.stopImmediatePropagation()

<!--Try it-->
function first(event) {
  console.log(1);
}
function second() {
  console.log(2);
}
function third() {
  console.log(3);
}
let button = document.getElementById("button");
let container = document.getElementById("container");
button.addEventListener("click", first);
button.addEventListener("click", second);
container.addEventListener("click", third);

Давайте предположим, что мы хотели добавить третью функцию, которая выводит 3 на консоль. В этом сценарии мы также переместим вторую функцию, чтобы она также находилась на кнопке. Теперь мы нанесем третий слой на контейнер.

Короче говоря: у нас есть два обработчика событий на кнопке, и нажатие <div#container> теперь выведет 3.

Это будет вести себя так же, как и раньше, и оно будет распространяться по дереву DOM и выводить 1, 2, 3 в таком порядке.

Использование Event.stopPropagation() и Event.stopImmediatePropagation()

Добавление Event.stopPropagation() к первой функции, например, так, выведет 1, 2 на консоль.

function first(event) {
  event.stopPropagation();
  console.log(1);
}

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

Как вы можете видеть в нашем примере, у нашей кнопки есть два обработчика щелчков, и это остановило распространение на ее родителей. Если вы хотите остановить все обработчики событий после первого, вот где появляется Event.stopImmediatePropagation().

function first(event) {
  event.stopImmediatePropagation();
  console.log(1);
}

Теперь первая функция действительно остановит родительские обработчики щелчков и все остальные обработчики щелчков. Консоль теперь напечатает только 1, тогда как если бы мы просто использовали Event.stopPropagation(), она напечатала бы 1, 2, и, не включая ни то, ни другое, напечатала бы 1, 2, 3.

#JavaScript #Начинающим
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу