Подтвердить что ты не робот

JQuery.on(); vs JavaScript.addEventListener();

Может кто-нибудь объяснить мне, почему существует разница в порядке выполнения обработчиков событий в зависимости от того, как они были прикреплены? В приведенном ниже примере я использую методы .on() и .addEventListener() для обработки определенного события на разных элементах DOM.

jsfiddle: http://jsfiddle.net/etsS2/

Я думал, что в этом конкретном примере порядок, в котором будут выполняться обработчики событий, будет зависеть от event-bubbling - так, начиная с исходного события target и перемещаясь до элемента document.

document.getElementById('outer').addEventListener('mouseup', function (event) {
//$('#outer').on('mouseup', function (event) {
    alert('This alert should not show up!');
}, false);

Если я раскомментирую версию on();, все работает так, как ожидалось, - есть ли разница в том, как jQuery обрабатывает события, противоположные обычным JavaScript?

4b9b3361

Ответ 1

Когда вы используете .on() на уровне документа, вы ждете, пока событие пузырится до этой точки. Обработчик событий для любого промежуточного контейнера уже вызывается.

Событие "bubbling" - это процесс, с помощью которого браузер ищет обработчики событий, зарегистрированные с родителями этого элемента, который был фактическим оригинальным получателем события. Он работает вверх в дереве DOM. Уровень документа - это уровень последний. Таким образом, ваш обработчик, зарегистрированный с помощью .on(), не будет работать до тех пор, пока этот уровень не будет достигнут. В то же время другой обработчик событий на "внешнем" уровне достигается первым, и он выполняется браузером.

Таким образом, return false; в обработчике, зарегистрированном с помощью .on(), в значительной степени бесполезен, так же как и вызов event.stopPropagation(). Помимо этого, смешивание регистрации обработчика собственных событий с работой, которую будет выполнять библиотека, например, jQuery, - это, пожалуй, очень плохая идея, если вы серьезно не знаете, что делаете.

Был вопрос который был задан почти так же, как этот, совсем недавно.

Ответ 2

Посмотрите версию addEventListener:

document.getElementById('outer').addEventListener('mouseup', function (event) {
    alert('This alert should not show up!');
}, false);

Это работает отлично, потому что третий аргумент useCapture, который указывает, следует ли использовать фазу захвата события.

Когда вы переключаетесь на версию jQuery:

$('#outer').on('mouseup', function (event) {
    alert('This alert should not show up!');
}, false);

Я думаю, что это третий аргумент, который просто переопределяет вашу функцию обработчика событий и заставляет обработчик событий ничего не делать, кроме return false;, который явно не является тем, что должно произойти.

Из jQuery docs (выделено мной):

Функция, выполняемая при срабатывании события. Значение false также разрешено как сокращенное выражение для функции, которая просто возвращает ложь.

Удалите аргумент false, и версия jQuery будет работать правильно:

$('#outer').on('mouseup', function (event) {
    alert('This alert should not show up!');
});

Обратите внимание, что alert должен отображаться, поэтому подход addEventListener работает правильно. См. Ответ @Pointy, почему это так.