Яка різниця між бурбанням подій та захопленням? Коли слід використовувати бульбашку проти захоплення?
Яка різниця між бурбанням подій та захопленням? Коли слід використовувати бульбашку проти захоплення?
Відповіді:
Пульсування та захоплення подій - це два способи поширення події в API HTML DOM, коли подія відбувається в елементі всередині іншого елемента, і обидва елементи зареєстрували ручку для цієї події. Режим поширення події визначає, в якому порядку елементи отримують подію .
Завдяки бульбашці подія спочатку захоплюється та обробляється найпотужнішим елементом, а потім передається зовнішнім елементам.
Захоплюючи подію, спочатку захоплюється найвіддаленіший елемент і передається внутрішнім елементам.
Захоплення також називається "хитрощі", що допомагає запам'ятати порядок розповсюдження:
струсити вниз, пузирити
Ще в старі часи Netscape виступав за захоплення подій, а Microsoft сприяла бурхливості подій. Обидва є частиною стандарту W3C Document Object Model Events Events (2000).
IE <9 використовує лише бульбашку подій , тоді як IE9 + та всі основні браузери підтримують і те, і інше. З іншого боку, ефективність пульсації подій може бути дещо нижчою для складних DOM.
Ми можемо використовувати addEventListener(type, listener, useCapture)
для реєстрації обробників подій в режимі барботування (за замовчуванням) або в режимі захоплення. Для використання моделі захоплення передайте третій аргумент як true
.
<div>
<ul>
<li></li>
</ul>
</div>
У наведеній вище структурі припустимо, що в li
елементі відбулася подія клацання .
В захопленні моделі, ця подія буде оброблятися з допомогою div
перших (обробники подій клацніть в div
згорить першим), то в ul
, то на останньому в цільовому елементі, li
.
У моделі міхура відбудеться навпаки: подія спочатку буде оброблятися елементом li
, потім - і ul
, нарешті, div
елементом.
Для отримання додаткової інформації див
У наведеному нижче прикладі, якщо натиснути будь-який із виділених елементів, ви побачите, що фаза захоплення потоку розповсюдження події відбувається спочатку, а потім фаза барботування.
var logElement = document.getElementById('log');
function log(msg) {
logElement.innerHTML += ('<p>' + msg + '</p>');
}
function capture() {
log('capture: ' + this.firstChild.nodeValue.trim());
}
function bubble() {
log('bubble: ' + this.firstChild.nodeValue.trim());
}
function clearOutput() {
logElement.innerHTML = "";
}
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', capture, true);
divs[i].addEventListener('click', bubble, false);
}
var clearButton = document.getElementById('clear');
clearButton.addEventListener('click', clearOutput);
p {
line-height: 0;
}
div {
display:inline-block;
padding: 5px;
background: #fff;
border: 1px solid #aaa;
cursor: pointer;
}
div:hover {
border: 1px solid #faa;
background: #fdd;
}
<div>1
<div>2
<div>3
<div>4
<div>5</div>
</div>
</div>
</div>
</div>
<button id="clear">clear output</button>
<section id="log"></section>
useCapture
тепер підтримується в IE> = 9. Джерело
triclkling
те саме, що capturing
? Про це Крокфорд розповідає Trickling v. Bubbling
у цій відео-розмові - youtube.com/watch?v=Fv9qT9joc0M&list=PL7664379246A246CB навколо 1 hr 5 minutes
.
trickle down
=> onElement
=>bubble up
Опис:
quirksmode.org має хороший опис цього. Коротко кажучи (скопійовано з quirksmode):
Захоплення події
Коли ви використовуєте захоплення подій
| | ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 \ / | | | ------------------------- | | Event CAPTURING | -----------------------------------
спочатку спрацьовує обробник події element1, останній обробник події елемента2.
Подія кипіла
Під час використання подій
/ \ ---------------| |----------------- | element1 | | | | -----------| |----------- | | |element2 | | | | | ------------------------- | | Event BUBBLING | -----------------------------------
спочатку запускається обробник події елемента2, обробляється подія елементу1.
Що використовувати?
Це залежить від того, що ви хочете зробити. Немає кращого. Різниця - це порядок виконання обробників подій. Більшу частину часу буде добре запускати обробників подій у фазі бурхливості, але також може знадобитися звільнити їх раніше.
Якщо є два елементи, елемент 1 і елемент 2. Елемент 2 знаходиться всередині елемента 1 і ми приєднуємо обробник подій з обома елементами, дозволяє сказати onClick. Тепер, коли ми натискаємо на елемент 2, тоді буде виконано eventHandler для обох елементів. Тепер тут питання в якому порядку буде виконуватися подія. Якщо подія, приєднана до елемента 1, виконується спочатку, це називається захопленням події, а якщо подія, приєднана до елемента 2, виконується спочатку, це називається перебоєм подій. Відповідно до W3C подія розпочнеться у фазі захоплення, поки не досягне цілі, повернеться до елемента, а потім почне кипіти
Стани захоплення та барботування відомі параметром useCapture методу addEventListener
eventTarget.addEventListener (тип, слухач, [, useCapture]);
За замовчуванням useCapture є помилковим. Це означає, що він перебуває у фазі бульбашки.
var div1 = document.querySelector("#div1");
var div2 = document.querySelector("#div2");
div1.addEventListener("click", function (event) {
alert("you clicked on div 1");
}, true);
div2.addEventListener("click", function (event) {
alert("you clicked on div 2");
}, false);
#div1{
background-color:red;
padding: 24px;
}
#div2{
background-color:green;
}
<div id="div1">
div 1
<div id="div2">
div 2
</div>
</div>
Будь ласка, спробуйте змінити істинне і хибне.
the event will start in the capturing phase untill it reaches the target comes back to the element and then it starts bubbling
. Я лише виявив, що в addEventListener є параметр, useCapture
який можна встановити на true або false; а в HTML 4.0 слухачі подій були вказані як атрибути елемента та useCapture defaults to false
. Чи можете ви зв’язатись із специфікацією, яка підтверджує те, що ви написали?
Я знайшов цей підручник на javascript.info дуже зрозумілим у поясненні цієї теми. І його підсумок з 3-х балами наприкінці справді говорить про вирішальні моменти. Я цитую його тут:
- Події спочатку фіксуються до глибокої цілі, а потім піднімаються. У IE <9 вони лише бульбашки.
- Усі обробники працюють на вибухових стадіях винятків
addEventListener
з останнім аргументомtrue
, що є єдиним способом зловити подію на захопленні.- Бублінг / захоплення можна зупинити
event.cancelBubble=true
(IE) абоevent.stopPropagation()
для інших браузерів.
Також є Event.eventPhase
майно, яке може повідомити вам, чи подія є цільовою чи походить з іншого місця.
Зауважте, що сумісність браузера ще не визначена. Я протестував його на Chrome (66.0.3359.181) та Firefox (59.0.3), і він там підтримується.
Розширюючись на вже чудовий фрагмент із прийнятої відповіді , це вихід з використанням eventPhase
властивості
var logElement = document.getElementById('log');
function log(msg) {
if (logElement.innerHTML == "<p>No logs</p>")
logElement.innerHTML = "";
logElement.innerHTML += ('<p>' + msg + '</p>');
}
function humanizeEvent(eventPhase){
switch(eventPhase){
case 1: //Event.CAPTURING_PHASE
return "Event is being propagated through the target's ancestor objects";
case 2: //Event.AT_TARGET
return "The event has arrived at the event's target";
case 3: //Event.BUBBLING_PHASE
return "The event is propagating back up through the target's ancestors in reverse order";
}
}
function capture(e) {
log('capture: ' + this.firstChild.nodeValue.trim() + "; " +
humanizeEvent(e.eventPhase));
}
function bubble(e) {
log('bubble: ' + this.firstChild.nodeValue.trim() + "; " +
humanizeEvent(e.eventPhase));
}
var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
divs[i].addEventListener('click', capture, true);
divs[i].addEventListener('click', bubble, false);
}
p {
line-height: 0;
}
div {
display:inline-block;
padding: 5px;
background: #fff;
border: 1px solid #aaa;
cursor: pointer;
}
div:hover {
border: 1px solid #faa;
background: #fdd;
}
<div>1
<div>2
<div>3
<div>4
<div>5</div>
</div>
</div>
</div>
</div>
<button onclick="document.getElementById('log').innerHTML = '<p>No logs</p>';">Clear logs</button>
<section id="log"></section>