Что такое всплывающее и захватывающее событие? - PullRequest
956 голосов
/ 06 января 2011

В чем разница между всплытием и захватом событий?Какую модель быстрее и лучше использовать?

Ответы [ 6 ]

1328 голосов
/ 06 января 2011

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

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

При захвате событие сначала захватывается самым внешним элементом и распространяется на внутренние элементы.

Захват также называется «каплей», что помогает запомнить порядок распространения:

стекают, всплывают

В прежние времена Netscape выступал за захват событий, в то время как Microsoft поощряла всплытие событий.Оба являются частью W3C События объектной модели документа * стандарт 1016 * (2000).

IE <9 использует <a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener" rel="noreferrer"> только всплывающее окно событий , тогда как 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>

Еще один пример на JSFiddle .

488 голосов
/ 06 января 2011

Описание:

quirksmode.org имеет хорошее описание этого. В двух словах (скопировано из quirksmode):

Захват событий

Когда вы используете захват событий

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

обработчик событий element1 срабатывает первым, обработчик событий element2 срабатывает последним.

Событие пузыряется

При использовании всплытия событий

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

обработчик событий element2 срабатывает первым, обработчик событий element1 срабатывает последним.


Что использовать?

Это зависит от того, что вы хотите сделать. Там нет лучше. Разница заключается в порядке выполнения обработчиков событий. В большинстве случаев будет нормально запускать обработчики событий в фазе пузырящиеся , но может также потребоваться запускать их раньше.

68 голосов
/ 04 марта 2014

Если есть два элемента, элемент 1 и элемент 2. Элемент 2 находится внутри элемента 1, и мы прикрепляем обработчик событий, причем оба элемента позволяют сказать onClick.Теперь, когда мы щелкнем по элементу 2, будет выполнен eventHandler для обоих элементов.Теперь здесь вопрос в том, в каком порядке будет выполняться событие.Если событие, связанное с элементом 1, выполняется первым, это называется захватом события, а если событие, связанное с элементом 2, выполняется первым, это называется всплывающим событием.Согласно W3C, событие начнется в фазе захвата, пока не достигнет цели, вернется к элементу, а затем начнет пузыриться

Состояния захвата и пузыри известны с помощью параметра useCapture метода addEventListener

eventTarget.addEventListener (type, listener, [, useCapture]);

По умолчанию useCapture имеет значение false.Это означает, что он находится в фазе барботирования.

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>

Пожалуйста, попробуйте изменить true и false.

23 голосов
/ 14 мая 2015

Мне показалось, что это руководство по javascript.info очень ясно объясняет эту тему. И его резюме из 3 пунктов в конце действительно говорит о важных моментах. Я цитирую это здесь:

  1. События сначала фиксируются до самой глубокой цели, а затем всплывают. В IE <9, они только пузырь. </li>
  2. Все обработчики работают за исключением стадии барботирования addEventListener с последним аргументом true, который является единственным способом поймать событие на этапе захвата.
  3. Барботирование / захват может быть остановлено event.cancelBubble = true (IE) или event.stopPropagation () для других браузеров.
5 голосов
/ 29 мая 2018

Также есть свойство 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>
1 голос
/ 27 марта 2019

Барботирование

  Event propagate to the Upto root element is Bubbling.

Захват

  Event propogate from body(root) element to eventTriggered Element is Capturing.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...