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
?
Ответы
Ответ 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, почему это так.