Я задавался вопросом, были ли event.preventDefault()
и return false
такие же.
Я сделал несколько тестов , и кажется, что
Если добавлен обработчик событий по старой модели, например
elem.onclick = function(){ return false; };
Затем
return false
предотвращает действие по умолчанию, напримерevent.preventDefault()
.Если обработчик событий добавлен с помощью
addEventListener
, например,elem.addEventListener( 'click', function(e){ return false; }, false );
Тогда
return false
не предотвращает действие по умолчанию.
Все ли браузеры так себя ведут?
Есть ли еще различия между event.preventDefault()
и return false
?
Где я могу найти документацию (я не смог в MDN) о том, return false
как вести себя event.preventDefault()
в некоторых случаях?
Мой вопрос касается только простого javascript, а не jQuery, поэтому, пожалуйста, не помечайте его как дубликат event.preventDefault () vs. return false , даже если оба вопроса имеют почти одинаковый заголовок.
return false
ведет себя иначе, чем простой JavaScript. Более того, на другой вопрос нет ответа, объясняющего разницу в простом JS (есть только комментарий, который это объясняет, но его трудно найти). Поэтому я считаю, что лучше задать два разных вопроса.Ответы:
W3C Document Object Model События Спецификация в п.1.3.1. В интерфейсах регистрации событий указано, что
handleEvent
в EventListener нет возвращаемого значения:под 1.2.4. Отмена события в документе также говорится, что
что должно отговорить вас от использования какого-либо эффекта, который возврат true / false может иметь в любом браузере и использовании
event.preventDefault()
.Обновить
Спецификация HTML5 фактически определяет, как обрабатывать возвращаемое значение по-другому. В разделе 7.1.5.1 спецификации HTML говорится, что
для всего, кроме события "наведения курсора".
Заключение
Я по-прежнему рекомендую использовать
event.preventDefault()
в большинстве проектов, поскольку вы будете совместимы со старой спецификацией и, следовательно, со старыми браузерами. Только если вам нужно поддерживать только самые современные браузеры, можно вернуть false для отмены.источник
stopPropagation()
,preventDefault()
иreturn false
: jsfiddle.net/m1L6of9x . В современных браузерах последние два ведут себя одинаково.Вот несколько примеров, которые могут помочь людям лучше понять свои проблемы и устранить их.
TL; DR
on*
обработчики событий (например,onclick
атрибут в элементе кнопки): вернуть false для отмены событияaddEventListener
это другой API, возвращаемые значения (напримерfalse
) игнорируются: useevent.preventDefault()
.onclick="<somejs>"
имеет свою собственную потенциальную путаницу, потому что<somejs>
заключен в тело функции onclick.getEventListeners
API инструментов разработчика браузера, чтобы увидеть, как выглядит ваш прослушиватель событий, чтобы устранить неполадки, если ваш обработчик событий ведет себя не так, как ожидалось.пример
Этот пример специфичен для
click
события со<a>
ссылкой ... но может быть обобщен для большинства типов событий.У нас есть якорь (ссылка) с классом,
js-some-link-hook
который мы хотим открыть в модальном окне и предотвратить любую навигацию по странице.Приведенные ниже примеры были запущены в google chrome (71) на MacOS Mojave.
Одна из основных ошибок заключается в предположении, что
onclick=functionName
это то же поведение, что и при использованииaddEventListener
Допустим, у нас есть тег привязки (ссылка), который мы хотим обрабатывать с помощью javascript, когда javascript включен. Мы не хотим, чтобы браузер переходил по ссылке при нажатии (поведение «предотвратить по умолчанию»).
<a href="https://www.example.com/url/to/go/to/when/no/javascript" class="js-some-link-hook">click me!</a>
атрибут onclick
function eventHandler (event) { // want to prevent link navigation alert('eventHandler ran'); return false; } function addEventListenerToElement () { var link = document.querySelector('.js-some-link-hook'); link.setAttribute('onclick', eventHandler); } addEventListenerToElement();
Затем запустите в консоли разработчика браузера:
var el = document.querySelector('a.js-some-link-hook'), listener = getEventListeners(el).click[0].listener; console.log(''+listener); // to avoid truncation of output
... и вы видите:
function onclick(event) { function eventHandler (event) {alert('eventHandler ran'); return false;} }
Это вообще не работает. При использовании
onclick=
вашего обработчика функция обернута в другую функцию.Вы можете видеть, что мое определение функции включено, но не вызывается, потому что я указал ссылку на функцию, не вызывая ее. т.е. нам
onclick="functionName()"
неonclick="functionName"
нужно убедиться, чтоfunctionName
он запускается при нажатии на элемент.Кроме того, вы можете видеть, что даже если моя функция была вызвана и моя функция вернула false ...
onclick
функция не вернет это ложное значение ... которое требуется для «отмены» события.Чтобы исправить это, мы можем установить
onclick
значение,return myHandlerFunc();
которое гарантирует, чтоonclick
возвращается возвращаемое значение (false) изmyHandlerFunc
.Вы также можете удалить
return false;
изmyHandlerFunc
и изменить какonclick
быть,myHandlerFunc(); return false;
но это не имеет смысла, поскольку вы, вероятно, захотите сохранить логику в своей функции обработчика.Обратите внимание, что при настройке
onclick
с помощью javascript , когда вы настраиваетеonclick
непосредственно в html, а не с помощью javascript (как в моих примерах),onclick
значение атрибута представляет собой строку типа, и все работает. Если вы настраиваетеonclick
с помощью javascript, вам нужно обратить внимание на тип. Если вы скажете,element.setAttribute('onclick', myHandlerFunc())
myHandlerFunc
будет запущен прямо сейчас, а результат будет сохранен в атрибуте ... а не запускаться при каждом щелчке. Вместо этого вы должны убедиться, что значение атрибута задано как строка.element.setAttribute('onclick', 'return myHandlerFunc();')
Теперь, когда мы видим, как это работает, мы можем изменить код, чтобы делать все, что захотим. Странный пример для иллюстрации (не используйте этот код):
function eventHandler (e) { // want to prevent link navigation alert('eventHandler ran'); console.log(e); return false; } function addEventListenerToElement () { var link = document.querySelector('.js-some-link-hook'); link.setAttribute('onclick', 'return ('+eventHandler+')(event);'); } addEventListenerToElement();
Вы видите, что мы заключили определение нашей функции eventHandler в строку. В частности: самоисполняющаяся функция с оператором возврата впереди.
Снова в консоли chrome devtools:
var el = document.querySelector('a.js-some-link-hook'), listener = getEventListeners(el).click[0].listener; console.log(''+listener); // to avoid truncation of output
... показывает:
function onclick(event) { return (function eventHandler (e) { // want to prevent link navigation alert('eventHandler ran'); console.log(e); return false; })(event); }
... так что да, это должно сработать. Разумеется, если мы нажмем на ссылку, мы получим предупреждение и, отклонив предупреждение, страница не будет перемещаться и не обновится.
Еще одно примечание о
onclick
... Если вы хотите получить и использоватьevent
параметр во время события, вы должны отметить, что он называется «событие». Вы можете получить к нему доступ в своем обработчике, используя имяevent
(доступно через область родительскойonclick
функции). Или вы можетеevent
создать свой обработчик, который будет принимать его в качестве параметра (лучше для тестирования) ... например,onclick="return myEventHandler(event);"
или как вы видите в предыдущем примере.addEventListener
function eventHandler (ev) { // want to prevent link navigation alert('eventHandler ran'); console.log(ev); return false; } function addEventListenerToElement () { var link = document.querySelector('.js-some-link-hook'); link.addEventListener('click', eventHandler, false); } addEventListenerToElement();
инструменты разработчика браузера:
var el = document.querySelector('a.js-some-link-hook'), listener = getEventListeners(el).click[0].listener; console.log(''+listener); // to avoid truncation of output
результат:
function eventHandler (ev) { // want to prevent link navigation alert('eventHandler ran'); console.log(ev); return false; }
Так что разница уже видна. С
addEventListener
мы не обернуты вonclick
функции. Наш обработчик получаетevent
параметр напрямую (и поэтому мы можем называть его как угодно). Также наш здесьreturn false
находится на «верхнем уровне», и нам не нужно беспокоиться о добавлении дополнительных операторов возврата, таких как withonclick
.Похоже, это должно работать. При переходе по ссылке получаем оповещение. Закройте предупреждение, и страница будет перемещаться / обновляться. т.е. событие НЕ было отменено возвратом false.
Если мы посмотрим на спецификацию (см. Ресурсы внизу), мы увидим, что наша функция обратного вызова / обработчика для addEventListener не поддерживает возвращаемый тип. Мы можем вернуть все, что захотим, но поскольку это не является частью API / интерфейса браузера, это не имеет никакого эффекта.
Решение: использовать
event.preventDefault()
вместоreturn false;
...function eventHandler (ev) { // want to prevent link navigation ev.preventDefault(); alert('eventHandler ran'); } function addEventListenerToElement () { var link = document.querySelector('.js-some-link-hook'); link.addEventListener('click', eventHandler, false); } addEventListenerToElement();
инструменты разработчика браузера ...
var el = document.querySelector('a.js-some-link-hook'), listener = getEventListeners(el).click[0].listener; console.log(''+listener); // to avoid truncation of output
дает ...
function eventHandler (ev) { // want to prevent link navigation ev.preventDefault(); alert('eventHandler ran'); }
...как и ожидалось.
Снова тестирование:
Таким образом, при
addEventListener
использованииevent.preventDefault()
as возврат false ничего не делает.Ресурсы
Спецификация html5 ( https://www.w3.org/TR/html5/webappapis.html#events ) сбивает с толку, потому что они используют оба
onclick
иaddEventListener
в своих примерах, и говорят следующее:Таким образом, похоже, это означает, что
return false
событие отменяется для обоихaddEventListener
иonclick
.Но если вы посмотрите на их связанное определение,
event-handler
вы увидите:https://www.w3.org/TR/html5/webappapis.html#event-handler
Таким образом, кажется, что
return false
отмена события действительно применяется только кonclick
(или вообщеon*
) обработчикам событий, а не к обработчикам событий, зарегистрированным черезaddEventListener
которые имеет другой API.Поскольку
addEventListener
API не входит в спецификацию html5 (толькоon*
обработчики событий) ... было бы менее запутанно, если бы ониon*
в своих примерах придерживались обработчиков событий стиля.источник
Разница между preventDefault, stopPropogation, return false
Действие по умолчанию - действие на стороне сервера при возникновении управляющего события.
Предположим, у нас есть элемент управления div, а внутри него есть кнопка. Итак, div - это родительский элемент управления кнопки. У нас есть щелчок на стороне клиента и событие нажатия кнопки на стороне сервера. Также у нас есть событие клика на стороне клиента для div.
При нажатии кнопки на стороне клиента мы можем управлять действиями родительского элемента управления и кода на стороне сервера, используя следующие три способа:
return false
- Это разрешает только клиентское событие элемента управления. Событие на стороне сервера и событие на стороне клиента родительского элемента управления не запускаются.preventDefault()
- Это разрешает клиентское событие элемента управления и его родительский элемент управления. Событие на стороне сервера, т.е. Действие по умолчанию элемента управления не запускается.stopPropogation()
- Это разрешает клиентское, а также серверное событие элемента управления. Событие на стороне клиента элемента управления недопустимо.источник
return false
распространение не прекращается, поэтому родительский контроль запускается ( демонстрация ). Более того, я не совсем понимаю, что вы имеете в виду под « событием щелчка на стороне сервера ».return false
предназначен только для IE,event.preventDefault()
поддерживается современными браузерами chrome, ff ...источник
return false
работает так же, какevent.preventDefault()
если бы обработчик событий был добавлен по старой модели