Невозможно понять параметр useCapture в addEventListener
Я прочитал статью в https://developer.mozilla.org/en/DOM/element.addEventListener но не в состоянии понять . Определение есть:
если true, useCapture указывает, что пользователь хочет инициировать захват. После инициирования захвата все события указанного типа будут отправлены зарегистрированному прослушивателю перед отправкой в любые EventTargets под ним в дереве DOM. События, которые бурлят вверх через дерево не вызовет прослушиватель, назначенный для использования capture.
в этом коде родительское событие запускается перед дочерним, поэтому я не могу понять его поведение.Объект Document имеет значение usecapture true, а дочерний div-значение usecapture false, после чего используется document usecapture.Итак, почему свойство document предпочтительнее дочернего.
function load() {
document.addEventListener("click", function() {
alert("parent event");
}, true);
document.getElementById("div1").addEventListener("click", function() {
alert("child event");
}, false);
}
<body onload="load()">
<div id="div1">click me</div>
</body>
9 ответов
события могут быть активированы в двух случаях: в начале ("захват") и в конце ("пузырь"). События выполняются в порядке их определения. Скажем, вы определяете 4 слушателя событий:
window.addEventListener("click", function(){alert(1)}, false);
window.addEventListener("click", function(){alert(2)}, true);
window.addEventListener("click", function(){alert(3)}, false);
window.addEventListener("click", function(){alert(4)}, true);
появится окно предупреждения в следующем порядке:
-
2
(сначала определяется с помощьюcapture=true
) -
4
(определяется второй с помощьюcapture=true
) -
1
(первое определенное событие сcapture=false
) -
3
(второе определенное событие сcapture=false
)
Я считаю, что эта диаграмма очень полезна для понимания фаз захвата / цели / пузыря: http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases
ниже, контент, извлеченный из ссылки.
этапы
событие отправляется по пути от корня дерева к этому целевому узлу. Затем его можно обрабатывать локально на уровне целевого узла или от предков любой цели выше в дерево. Диспетчеризация событий (также называемая распространением событий) происходит в три этапа и в следующем порядке:
- фаза захвата: событие отправляется предкам цели от корня дерева до прямого родителя целевого узла.
- целевая фаза: событие отправляется на целевой узел.
- пузырящаяся фаза: событие отправляется в цель предки от прямого родителя целевого узла до корня из дерево.
предки цели определяются до первоначальной отправки события. Если целевой узел удаляется во время диспетчеризации или добавляется или удаляется предок целевого объекта, распространение событий всегда будет основываться на целевом узле и предках целевого объекта, определенных до отправки.
некоторые события могут не обязательно выполнять три фазы потока событий DOM, например, событие может быть только определяется для одной или двух фаз. Например, события, определенные в этой спецификации, всегда будут выполнять фазы захвата и цели, но некоторые не будут выполнять фазу пузырьков ("пузырящиеся события" по сравнению с "не пузырящимися событиями", см. Также событие.пузыри атрибут).
захват события vs Bubble Event
- событие захвата будет отправлено перед событием пузыря
- порядок распространения событий
- Родитель Захвата
- Детская Захвата
- Дети Пузырь
- Родитель Пузыря
( stopPropagation()
остановит поток )
| A
-----------------|--|-----------------
| Parent | | |
| -------------|--|----------- |
| |Children V | | |
| ---------------------------- |
| |
--------------------------------------
var parent = document.getElementById('parent'),
child = document.getElementById('child');
child.addEventListener('click', function(e){
console.log('Child Capture, with capture');
// e.stopPropagation();
}, true);
child.addEventListener('click', function(e){
console.log('Child Bubble');
// e.stopPropagation();
}, false);
parent.addEventListener('click', function(e){
console.log('Parent Capture, with capture');
// e.stopPropagation();
}, true);
parent.addEventListener('click', function(e){
console.log('Parent Bubble');
// e.stopPropagation();
}, false);
<div id="parent">
<button id="child">Click</button>
</div>
когда вы говорите useCapture = true, события выполняются сверху вниз в фазе захвата, когда false он делает пузырь снизу вверх.
пример кода:
<div id="div1" style="background:#9595FF">
Outer Div<br />
<div id="div2" style="background:#FFFFFF">
Inner Div
</div>
</div>
код Javascript:
d1 = document.getElementById("div1");
d2 = document.getElementById("div2");
если для обоих установлено значение false
d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},false);
исполняет: Onclicking внутренний Div, оповещения отображаются как: Div 2 > Div 1
здесь скрипт выполняется из внутреннего элемента: Event Bubbling (useCapture имеет значение false)
div 1 имеет значение true, а div 2-значение false
d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},false);
исполняет: Onclicking внутренний Div, оповещения отображаются как: Div 1 > Div 2
здесь скрипт выполняется из предка / внешнего элемента: захват события (useCapture имеет значение true)
div 1 имеет значение false, а div 2-true
d1.addEventListener('click',function(){alert("Div 1")},false);
d2.addEventListener('click',function(){alert("Div 2")},true);
исполняет: Onclicking внутренний Div, оповещения отображаются как: Div 2 > Div 1
здесь скрипт выполняется из внутреннего элемента: Event Bubbling (useCapture имеет значение false)
div 1 имеет значение true, а div 2-Значение правда
d1.addEventListener('click',function(){alert("Div 1")},true);
d2.addEventListener('click',function(){alert("Div 2")},true);
исполняет: Onclicking внутренний Div, оповещения отображаются как: Div 1 > Div 2
здесь скрипт выполняется из элемента ancestor / outer: захват события, так как useCapture имеет значение true
все о моделях событие: http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow
Вы можете поймать событие в фазе пузырьков или в фазе захвата. Ваш выбор.
Взгляните на http://www.quirksmode.org/js/events_order.html - вы найдете его очень полезным.
учитывая три фазы события путешествия:
- на фазы захвата: событие отправляется предкам цели от корня дерева до прямого родителя цели узел.
- на целевой фазы: событие отправляется на целевой узел.
- на пузырящейся фазы: событие отправляется предкам цели от прямого родителя объекта целевой узел к корню дерево.
useCapture
указывает, для каких фаз событие путешествия будет:
Если
true
, usecapture присвоено указывает, что пользователь желает добавить событие прослушиватель только для фазы захвата, т. е. этот прослушиватель событий не будет запускаться во время фазы мишени и пузырьков. Еслиfalse
, в прослушиватель событий будет срабатывать только во время цели и пузырьков фазы
источник такой же, как второй лучший ответ: https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases
резюме:
на DOM
спецификаций, описанных в:
https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/events.html#Events-phases
работает следующим образом:
событие отправляется по пути от корня (document
) от дерева до целевом узле. Целевой узел является самым глубоким HTML
элемент, т. е. событие.цель. Диспетчеризация событий (также называемое Событие распространение) происходит в три фазы и в следующем порядке:
-
фаза захвата: событие отправляется предкам цели из корня дерева (
document
) для прямого родителя целевого узла. -
цель этапа: событие отправляется на целевой узел. Целевая фаза всегда находится на самом глубоком
html
элемент, на котором событие было dispachted. - пузырящаяся фаза: событие отправляется предкам цели от прямого родителя целевого узла к корню дерева.
пример:
// bubbling handlers, third argument (useCapture) false (default)
document.getElementById('outerBubble').addEventListener('click', () => {
console.log('outerBubble');
}, false)
document.getElementById('innerBubble').addEventListener('click', () => {
console.log('innerBubble');
}, false)
// capturing handlers, third argument (useCapture) true
document.getElementById('outerCapture').addEventListener('click', () => {
console.log('outerCapture');
}, true)
document.getElementById('innerCapture').addEventListener('click', () => {
console.log('innerCapture');
}, true)
div:hover{
color: red;
cursor: pointer;
}
<!-- event bubbling -->
<div id="outerBubble">
<div id="innerBubble">click me to see Bubbling</div>
</div>
<!-- event capturing -->
<div id="outerCapture">
<div id="innerCapture">click me to see Capturing</div>
</div>
приведенный выше пример действительно иллюстрирует разницу между пузырями событий и захватом событий. При добавлении прослушивателей событий с addEventListener
, есть третий элемент, называемый useCapture. Это boolean
который при установке в true
позволяет прослушивателю событий использовать захват событий вместо пузырьков событий.
в нашем примере, когда мы устанавливаем аргумент useCapture в false
мы видим, что бурление происходит. Сначала запускается событие на целевой фазе (logs innerBubble), а затем через событие bubbling запускается событие в родительском элементе (logs outerBubble).
когда мы устанавливаем аргумент useCapture в true
мы видим, что события во внешнем <div>
is выстрелил первым. Это связано с тем, что событие теперь запускается в фазе захвата, а не в фазе пузырьков.
порядок определения имеет значение, только если элементы находятся на одном уровне. Если вы изменить порядок в коде вы получите те же результаты.
однако, если вы отмените параметр useCapture для двух обработчиков событий, обработчик дочерних событий ответит раньше, чем родительский. Причина этого заключается в том, что обработчик дочерних событий теперь будет запускаться на этапе захвата, который предшествует фазе пузырьков, в которой будет Родительский обработчик событий вызванный.
Если вы установите useCapture в true для обоих обработчиков событий-независимо от порядка определения-Родительский обработчик событий будет запущен первым, потому что он приходит до ребенка в фазе захвата.
и наоборот, если вы установите useCapture в false для обоих обработчиков событий-опять же, независимо от порядка определения-обработчик дочерних событий будет запущен первым, потому что он приходит до родителя в фазе пузырьков.