preventDefault(): отмена стандартного поведения в JavaScript

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

Метод event.preventDefault() отменяет такое действие. Его вызывают, когда код берёт это действие на себя и предлагает пользователю понятную замену. Сам метод ничего не отправляет, не открывает и не закрывает - он только отменяет действие браузера.

Стандартное поведение

СобытиеОбычное действие браузера
Клик по ссылкеПереход по адресу из href
submit формыОтправка формы и переход или перезагрузка страницы
contextmenuОткрытие контекстного меню браузера
Нажатие некоторых клавишНапример, переход по Tab или прокрутка страницы

Отменять поведение стоит только тогда, когда оно действительно мешает задаче. Если нужно запретить работу с полем, лучше использовать disabled или readonly. Для проверки обязательного поля подходят required и другие HTML-атрибуты.

Отмена перехода по ссылке

После клика по ссылке браузер переходит по адресу из href. Иногда переход нужно отложить, например когда пользователь пытается уйти со страницы с несохранёнными изменениями.

<a class="profile-link" href="/profile">Перейти к профилю</a>

<p class="leave-warning" hidden>
  Сначала сохраните изменения
</p>
const profileLink = document.querySelector('.profile-link');
const leaveWarning = document.querySelector('.leave-warning');
let hasUnsavedChanges = true;

profileLink.addEventListener('click', function (event) {
  if (!hasUnsavedChanges) {
    return;
  }

  event.preventDefault();
  leaveWarning.hidden = false;
});

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

Не превращайте ссылку в кнопку только с помощью preventDefault(). Если клик должен выполнять действие внутри интерфейса, используйте элемент button.

Отмена контекстного меню

Событие contextmenu возникает, когда пользователь запрашивает контекстное меню. Обычно это происходит по правому клику. Если интерфейс показывает собственный набор действий, стандартное меню можно отменить.

<div class="note-area">
  Нажмите здесь правой кнопкой мыши
</div>

<div class="note-actions" hidden>
  <button type="button">Редактировать заметку</button>
  <button type="button">Удалить заметку</button>
</div>
const noteArea = document.querySelector('.note-area');
const noteActions = document.querySelector('.note-actions');

noteArea.addEventListener('contextmenu', function (event) {
  event.preventDefault();
  noteActions.hidden = false;
});

После правого клика браузерное меню не появится, а вместо него станут видны действия с заметкой. В реальном интерфейсе собственное меню должно быть доступно не только мышью, но и с клавиатуры. Не отключайте контекстное меню просто ради запрета копирования - это ухудшает работу с сайтом.

Отмена и всплытие

preventDefault() не останавливает само событие. Другие обработчики и обработчики родительских элементов всё равно могут получить его. Метод отменяет только действие браузера.

Если задача связана с тем, чтобы событие не дошло до родителя, это уже управление распространением события. Для этого существует другой механизм - stopPropagation().

Когда метод не сработает

Отменить можно только событие, у которого есть отменяемое стандартное действие. Свойство event.cancelable показывает, можно ли это сделать. Если оно равно false, вызов preventDefault() ничего не изменит.

if (event.cancelable) {
  event.preventDefault();
}

В пассивном обработчике с опцией { passive: true } отмена тоже не работает. Такой обработчик сообщает браузеру, что код не будет блокировать стандартное действие. Кроме того, в обработчике, назначенном через addEventListener(), запись return false не заменяет вызов preventDefault().

Итого

event.preventDefault() отменяет стандартное действие браузера: отправку формы, переход по ссылке, контекстное меню или другое отменяемое поведение. Используйте его только вместе с понятной заменой. Он не останавливает всплытие события и не сработает для неотменяемого или пассивного обработчика.