Останавливает ли stopPropgation распространение события на этапе захвата?

Я просматривал http://www.quirksmode.org/js/events_order.html. и в этой части неоднозначно:

В модели Microsoft вы должны установить для свойства cancelBubble события значение true.

window.event.cancelBubble = true

В модели W3C вы должны вызвать метод stopPropagation() события.

e.stopPropagation()

Это останавливает все распространение события в фазе всплытия.

Итак, мой вопрос:

  • Когда прослушиватель событий настроен на прослушивание на этапе захвата, не продолжает ли он автоматически распространяться на внутренние элементы?
  • Или, если он продолжает распространяться, вызов e.stopPropagation() останавливает его или это работает только для фазы пузыря?

person yic    schedule 17.09.2012    source источник


Ответы (3)


Нет, прослушиватель событий не останавливает распространение каких-либо событий, если только вы не укажете это явно. Часть, о которой вы говорите, касается конкретно фазы пузыря. Модель IE не поддерживает захват событий — точка. фаза захвата — это то, что предшествует фазе всплытия:

Top of the DOM --->event--->traverses--->to--->[target]+[event]-| (capture phase)
      /\                                                       \/
      |------------------------to--------back up-----------------  (bubble up)
person Elias Van Ootegem    schedule 17.09.2012
comment
Спасибо. Похоже, что IE8 не поддерживает захват событий, но IE9 поддерживает: msdn.microsoft.com/en-us/library/windows/apps/hh453039.aspx - person yic; 17.09.2012
comment
Мой вопрос: останавливает ли e.stopPropagation() только распространение пузырьков или как распространение захвата, так и пузырьков? Возможный ответ зависит от браузера. - person yic; 17.09.2012
comment
Краткий ответ: stopPropagation останавливает событие в обоих случаях. Как показывает (ужасная) ASCII-диаграмма, наборы событий начинаются с document и спускаются вниз в DOM к элементу, в котором произошло событие. После этого он возвращается к документу. На каждом промежуточном шаге этот процесс может быть остановлен, независимо от того, происходит ли это во время фазы захвата или пузырька. - person Elias Van Ootegem; 17.09.2012
comment
Я думаю, что понимаю тебя. Спасибо, что так хорошо объяснили. Таким образом, W3C, если у меня есть и прослушиватель событий захвата, и прослушиватель событий пузырьков: - Если бы только прослушиватель событий захвата сделал e.stopPropagation(), прослушиватель событий пузырьков не увидел бы событие. - Если прослушиватель событий пузырьков сделал e.stopPropagation(), прослушиватель событий захвата все равно увидит событие, так как событие сначала прошло захват. Это правильно? - person yic; 18.09.2012
comment
Не совсем. В первой части вы правы: остановка распространения события означает, что событие не достигнет фазы пузырька, если вы остановите событие во время всплытия, все прослушиватели захвата будут запущены до этого: first событие проходит фазу захвата, затем всплывает. Если вы остановитесь во время пузырения, фаза захвата завершена... - person Elias Van Ootegem; 18.09.2012
comment
Хорошо, спасибо :) Я думаю, мы на самом деле говорим одно и то же... если вы остановитесь во время всплытия, фаза захвата завершена, ... поэтому остановка во время всплытия не должна мешать слушателям, которые слушают в фазе захвата, обрабатывать событие. - person yic; 19.09.2012
comment
@yic: Нет, необходимо сделать важное различие: если вы остановите событие на этапе пузырька, у которого есть прослушиватели как для этапов захвата, так и для этапов пузырьков, прослушиватели на этапе захвата обработали событие. Просто не остановили. Таким образом, вы можете настроить обработчик захвата для оповещения о чем-то, а прослушиватель пузырьков оповещает о чем-то еще и вызывает метод stopPropagation. Это приведет к отображению двух предупреждений - person Elias Van Ootegem; 19.09.2012
comment
Я согласен с этим, это именно то, что я пытался выразить! Я верю, что мы действительно говорим об одном и том же! Это смешно :) - person yic; 20.09.2012
comment
Невероятно, как этот ответ до сих пор на самом деле не отвечает на вопрос (остановит ли это вызов e.stopPropagation()?), и нам нужно прочитать комментарии. Ответ Леона Ли намного лучше. - person Stijn de Witt; 01.05.2018

Краткий ответ: порядок:

  1. Захват (вниз)
  2. Цель
  3. Пузыриться).

Если вы вызываете e.stopPropagation() на этапе захвата (путем установки 3-го аргумента addEventListener() в значение true), он останавливается на 1, поэтому 2 и 3 не могут его получить.

Если вы вызываете e.stopPropagation() в фазе пузырька (устанавливая 3-й аргумент addEventListener() в false или просто не назначая его), 1 и 2 уже завершены, поэтому это просто предотвращает событие всплывает с уровня, где вы вызываете stopPropagation().

person LeOn - Han Li    schedule 26.10.2015
comment
Я думаю, что вопрос более конкретен. Препятствует ли event.stopPropagation() прохождению события через оставшихся предков event.target? Или это предотвращает только фазы 2 и 3, тогда как фаза 1 завершится несмотря ни на что? - person GetFree; 31.03.2018
comment
Это гораздо лучший ответ, чем тот, который принят в настоящее время. - person Luis Crespo; 27.10.2020

stopPropagation() не остановит вызов захваченного обработчика событий. stopPropagation() остановит вызов обработчика всплывающих окон.

Jsfiddle

var outputDiv = document.getElementById('output');

function log(msg) {
  outputDiv.insertAdjacentHTML('afterend', msg + '<br>');
}

/////////////////////
//Bubbling listeners
/////////////////////
document.getElementById('row1').addEventListener('click', function(e) {
  log('Bubbling row1 listener called');
  e.stopPropagation();
}, false);

document.getElementById('row2').addEventListener('click', function(e) {
  log('Bubbling row2 listener called');
  //NO stopPropagation on this one.
}, false);

document.getElementById('table').addEventListener('click', function() {
  log('Bubbling table listener called');
}, false);


document.addEventListener('click', function() {
  log('Bubbling document listener called');
}, false);

/////////////////////
//Capturing listeners
/////////////////////
document.addEventListener('click', function() {
  log('Capturing document listener called');
}, true);

document.getElementById('table').addEventListener('click', function() {
  log('Capturing table listener called');
}, true);
#outputwrapper {
  border: 1px solid black;
  height: 300px;
  overflow: scroll;
}
<table id="table" border="1">
  <tbody>
    <tr>
      <td id="row1">
        This row has stopPropagation
      </td>
    </tr>
    <tr>
      <td id="row2">
        This row does not have stopPropagation
      </td>
    </tr>
  </tbody>
</table>
<br>Output
<br>
<div id="outputwrapper">
  <div id="output"></div>
</div>

person Ravi Gidwani    schedule 16.05.2015
comment
У вас есть две проблемы. Во-первых, это строки 1 и строки 2, а не столбцы. Во-вторых, обработчик событий строки 2 на самом деле не находится в фазе захвата, поскольку отсутствует третий аргумент его addEventListener. Принятый ответ правильный. - person Chen; 17.07.2015
comment
@ Чен, во-первых, я согласен с неправильным названием столбца. На самом деле я сократил код, удалив некоторые столбцы, и у меня остался этот код. - person Ravi Gidwani; 31.07.2015
comment
@Chen Я изменил код, чтобы отразить то, что я пытался объяснить. - person Ravi Gidwani; 31.07.2015