Различные способы выполнения обработчика событий элемента на этапе захвата

#javascript #html

#javascript #HTML

Вопрос:

Я могу заставить элементы выполнять свои обработчики на этапе захвата следующим образом:

elem.addEventListener('event', handler, {once: false, capture: true});

Установка третьего аргумента в true также работает — есть ли очевидная причина, почему? Имеет ли выполнение этого таким образом какие-либо побочные эффекты?

Ответ №1:

Логический параметр был оригинальным способом, которым он работал, до того, как был введен options объект. Вот причина, по которой он (все еще) работает: для обратной совместимости.

Смотрите документы:

Синтаксис

 target.addEventListener(type, listener [, options]);
target.addEventListener(type, listener [, useCapture]);
  

Вы можете либо передать логическое значение useCapture (оно существует уже более длительное время), либо объект options, который позволяет вам указывать capture также и другие вещи (например, once ).

Таким образом, addEventListener(..., true) это то же самое, что и addEventListener(..., { capture: true }) , и побочных эффектов нет.

options Форма объекта существует с ~ 2016 года. Проверьте caniuse, чтобы увидеть, какие клиенты поддерживают его.

Ответ №2:

Если у вас нет других прослушивателей событий, которые могут выполнять какие-либо действия с событием или страницей, то, как правило, не имеет значения, куда вы подключаете своего прослушивателя. Если это единственный прослушиватель, вы можете прикрепить его к элементу, или к одному из его родителей, или к документу или window , и к любому из тех, кто находится на этапе создания пузырьков или захвата — и в большинстве случаев это не будет иметь значения.

Основное назначение прослушивателя захвата — установить порядок, в котором выполняются обработчики событий. Когда событие отправляется элементу, оно сначала захватывает вниз от window , запуская прослушиватели захвата на window , затем на document , затем на промежуточных элементах, пока не достигнет самого глубокого элемента, который привел к событию. На самом глубоком элементе будут запущены как прослушиватели захвата, так и загрузочные прослушиватели в том порядке, в котором они были прикреплены. Затем событие начнет «пузыриться», запуская прослушиватели пузырьков для этого самого глубокого элемента, затем для промежуточных элементов, затем для документа, а затем для окна.

Чтобы проиллюстрировать, посмотрите, как прослушиватель захвата запускается первым здесь, когда слушатели подключены к родительскому:

 document.addEventListener('click', () => console.log('bubbling'));
document.addEventListener('click', () => console.log('capturing (method 1)'), true);
document.addEventListener('click', () => console.log('capturing (method 2)'), { capture: true });  
 <button>click</button>  

Если элемент, к которому подключается прослушиватель, является тем же элементом, который отправляет событие (например, если у вас есть button элемент без дочерних элементов, на который нажимается), то захват против пузырьков не имеет никакого эффекта — все прослушиватели будут выполняться в том порядке, в котором они были подключены, независимо от useCapture .

Прослушиватели с пузырьками могут использоваться для предотвращения всплывания события вверх и запуска родительских прослушивателей. Аналогично, захват прослушивателей может предотвратить захват события вниз и запуск дочерних прослушивателей.

 window.addEventListener('click', (e) => {
  e.stopPropagation();
  console.log('capturing, stopPropagation')
}, true);
document.querySelector('button').addEventListener('click', () => console.log('at target'));  
 <button>click</button>  

Выше прослушиватель захвата вызывался stopPropagation для события, предотвращая его распространение вниз на дочерний прослушиватель, который был бы запущен позже, если бы не stopPropagation .

Для третьего аргумента addEventListener вы можете использовать { capture: useCapture } или просто useCapture в качестве аргумента, согласно спецификации:

Метод addEventListener (тип, обратный вызов, параметры) при вызове должен выполнять следующие шаги:

  1. Пусть capture, passive и once будут результатом сглаживания дополнительных опций.

Где «сглаживание больше» делает:

  1. Пусть захват будет результатом сглаживания параметров.

Где «сглаживание» делает:

  1. Если значение options является логическим, то верните значение options.
  2. Верните параметры захвата.

Комментарии:

1. Это хороший ответ на вопрос «в чем разница между прослушивателем событий, запускаемым на этапе захвата, и фазой пузырьков», но это не то, что было задано. Казалось бы, OP уже знает, что делает этап захвата. Они спросили конкретно о том, как получилось, что 3-й аргумент true вместо { capture: true } также работает, на что вы не ответили.