Пошук уроків, статей та іншого контенту
Навчитеся скасовувати стандартну поведінку посилань, форм та інших елементів через preventDefault.
Браузер автоматично виконує певні дії у відповідь на події:
клік по посиланню відкриває його адресу;
відправлення форми перезавантажує сторінку або переходить за адресою action;
натискання кнопки типу submit запускає відправлення форми;
перетягування зображення може почати його переміщення;
клік правою кнопкою відкриває контекстне меню.
Таку автоматичну поведінку називають стандартною дією події.
Метод event.preventDefault() скасовує стандартну дію, але не зупиняє поширення події та не забороняє виконання інших обробників.
element.addEventListener("event", (event) => {
event.preventDefault();
});Наприклад, посилання може відкривати сторінку лише після додаткового підтвердження користувача:
<a id="delete-link" href="/delete-account">Видалити обліковий запис</a>
<script>
const deleteLink = document.querySelector("#delete-link");
deleteLink.addEventListener("click", (event) => {
const confirmed = confirm("Ви справді хочете видалити обліковий запис?");
if (!confirmed) {
event.preventDefault();
}
});
</script>Якщо користувач натисне Скасувати, браузер не перейде за адресою /delete-account.
Важливо: preventDefault() потрібно викликати саме для тієї події, стандартну дію якої потрібно скасувати.
Форма за замовчуванням надсилає дані на адресу з атрибута action. Якщо action не вказано, зазвичай використовується поточна адреса сторінки. Після цього браузер може перезавантажити документ.
У сучасних вебзастосунках форму часто обробляють JavaScript-кодом:
скасовують стандартне відправлення;
перевіряють дані;
надсилають їх через fetch() або обробляють локально.
<form id="registration-form">
<label>
Ім'я користувача:
<input id="username" name="username" required>
</label>
<label>
Електронна пошта:
<input id="email" name="email" type="email" required>
</label>
<button type="submit">Зареєструватися</button>
</form>
<p id="message"></p>
<script>
const form = document.querySelector("#registration-form");
const message = document.querySelector("#message");
form.addEventListener("submit", (event) => {
event.preventDefault();
const formData = new FormData(form);
const username = formData.get("username");
const email = formData.get("email");
message.textContent =
`Дані підготовлено: ${username}, ${email}`;
});
</script>Подію потрібно обробляти на submit форми, а не лише на click кнопки. Форма може бути відправлена не тільки кліком:
натисканням Enter в одному з полів;
викликом form.requestSubmit();
взаємодією з допоміжними технологіями.
Обробник submit охоплює всі ці випадки.
Якщо форма має атрибути required, type="email" та інші обмеження, браузер спочатку виконує вбудоване перевіряння.
Обробник submit зазвичай не викликається, якщо дані не проходять таку перевірку. Щоб отримати можливість повністю перевіряти дані власним кодом, можна використати атрибут novalidate:
<form id="profile-form" novalidate>
<input
id="profile-name"
name="name"
required
minlength="2"
placeholder="Ваше ім'я"
>
<button type="submit">Зберегти</button>
</form>
<p id="profile-error"></p>
<script>
const form = document.querySelector("#profile-form");
const nameInput = document.querySelector("#profile-name");
const error = document.querySelector("#profile-error");
form.addEventListener("submit", (event) => {
event.preventDefault();
if (nameInput.value.trim().length < 2) {
error.textContent = "Ім'я має містити щонайменше два символи.";
return;
}
error.textContent = "Профіль збережено.";
});
</script>novalidate не скасовує подію submit. Він вимикає автоматичне браузерне перевіряння перед відправленням.
Кнопка всередині форми за замовчуванням має тип submit, якщо її атрибут type не вказано:
<form>
<button>Відправити форму</button>
</form>Щоб кнопка виконувала лише JavaScript-дію та не надсилала форму, вкажіть type="button":
<form id="settings-form">
<button type="button" id="reset-button">Скинути налаштування</button>
<button type="submit">Зберегти</button>
</form>
<script>
const resetButton = document.querySelector("#reset-button");
resetButton.addEventListener("click", () => {
console.log("Налаштування скинуто");
});
</script>Іноді замість зміни типу кнопки використовують preventDefault():
resetButton.addEventListener("click", (event) => {
event.preventDefault();
});Але для кнопки, яка не повинна надсилати форму за призначенням, зрозуміліше вказати type="button" у HTML.
Подію contextmenu браузер зазвичай обробляє відкриттям контекстного меню. Її можна скасувати:
<div id="protected-area">
Клікніть тут правою кнопкою миші
</div>
<script>
const protectedArea = document.querySelector("#protected-area");
protectedArea.addEventListener("contextmenu", (event) => {
event.preventDefault();
alert("Власне контекстне меню ще не реалізовано.");
});
</script>Скасування контекстного меню може бути виправданим для спеціальних інтерфейсів, але не варто без потреби обмежувати стандартні можливості браузера.
Зображення та деякі інші елементи можуть перетягуватися браузером за замовчуванням. Щоб заборонити це:
<img
id="logo"
src="logo.png"
alt="Логотип"
draggable="true"
>
<script>
const logo = document.querySelector("#logo");
logo.addEventListener("dragstart", (event) => {
event.preventDefault();
});
</script>У реальному прикладі файл logo.png має існувати поруч із HTML-файлом. Такий підхід часто використовують у власних компонентах перетягування, де браузерна поведінка заважає реалізації.
preventDefault() і stopPropagation() — різні методиЦі методи вирішують різні завдання.
preventDefault()Скасовує стандартну дію браузера:
event.preventDefault();Наприклад, посилання не відкриється, а форма не буде відправлена.
stopPropagation()Зупиняє поширення події до інших елементів:
event.stopPropagation();Наприклад, подія не перейде від дочірнього елемента до батьківського під час спливання.
Їх можна викликати разом, але це не робить методи взаємозамінними:
button.addEventListener("click", (event) => {
event.preventDefault();
event.stopPropagation();
});У більшості випадків не потрібно зупиняти поширення лише для того, щоб скасувати стандартну дію.
preventDefault()Під час делегування обробник встановлюють на спільного предка. Це зручно для багатьох посилань або динамічно створених елементів.
<nav id="navigation">
<a href="/home">Головна</a>
<a href="/products">Товари</a>
<a href="/account" data-requires-auth>Мій профіль</a>
</nav>
<script>
const navigation = document.querySelector("#navigation");
navigation.addEventListener("click", (event) => {
const link = event.target.closest("a");
if (!link || !navigation.contains(link)) {
return;
}
if (link.hasAttribute("data-requires-auth")) {
const isAuthenticated = false;
if (!isAuthenticated) {
event.preventDefault();
alert("Спочатку увійдіть до облікового запису.");
}
}
});
</script>Тут подія виникає на посиланні, але обробляється елементом nav. Метод closest() допомагає знайти найближче посилання, на якому або всередині якого відбувся клік.
defaultPreventedПісля виклику preventDefault() властивість event.defaultPrevented стає true.
Це дозволяє іншому обробнику перевірити, чи вже було скасовано стандартну дію:
document.addEventListener("click", (event) => {
if (event.defaultPrevented) {
console.log("Стандартну дію вже скасовано.");
}
});Властивість корисна, коли кілька обробників працюють з однією подією.
preventDefault() не працюєСкасувати можна лише подію, яка допускає скасування. Це перевіряють через event.cancelable:
element.addEventListener("some-event", (event) => {
if (event.cancelable) {
event.preventDefault();
}
});Для типових подій, таких як click, submit і contextmenu, стандартна дія зазвичай є скасованою. Але не кожна подія має дію, яку можна скасувати.
Є ще одна особливість — обробники сенсорних і колісних подій можуть бути пасивними. У пасивному обробнику браузер очікує, що preventDefault() не викликатиметься:
element.addEventListener("touchmove", (event) => {
event.preventDefault();
}, { passive: false });Опцію { passive: false } слід використовувати лише тоді, коли справді потрібно блокувати стандартну прокрутку або іншу дію. Без необхідності не варто втручатися в прокручування сторінки.
preventDefault() поза обробником подіїМетод належить об’єкту події, тому його потрібно викликати через параметр обробника:
link.addEventListener("click", (event) => {
event.preventDefault();
});Виклик preventDefault() без event спричинить помилку.
Якщо потрібно заборонити відправлення форми, краще обробляти submit, а не тільки click кнопки:
form.addEventListener("submit", (event) => {
event.preventDefault();
});return falseУ старому коді можна зустріти:
<a href="/next-page" onclick="return false">Перейти</a>Це застарілий і менш гнучкий підхід. Для сучасного JavaScript використовуйте addEventListener() та event.preventDefault().
preventDefault() безумовноЯкщо скасувати дію посилання завжди, воно ніколи не працюватиме як навігація:
link.addEventListener("click", (event) => {
event.preventDefault();
});Скасовуйте дію лише тоді, коли це справді потрібно:
link.addEventListener("click", (event) => {
if (!userIsAuthenticated) {
event.preventDefault();
}
});preventDefault() замість правильної HTML-структуриЯкщо кнопка не повинна відправляти форму, використовуйте type="button". Якщо поле має бути обов’язковим, використовуйте required. JavaScript має доповнювати HTML, а не без потреби замінювати його можливості.
preventDefault() для захисту сервераСкасування переходу або відправлення форми впливає лише на поведінку браузера. Воно не захищає дані та не замінює перевірку на сервері. Будь-які важливі дані потрібно повторно перевіряти на сервері.
Створіть форму пошуку з такими вимогами:
Форма не повинна перезавантажувати сторінку.
Якщо поле пошуку порожнє, покажіть повідомлення про помилку.
Якщо поле заповнене, виведіть пошуковий запит у консоль.
Обробка має працювати і після натискання кнопки, і після натискання Enter.
Один із можливих варіантів:
<form id="search-form">
<label>
Пошук:
<input id="search-input" name="query">
</label>
<button type="submit">Знайти</button>
</form>
<p id="search-message"></p>
<script>
const searchForm = document.querySelector("#search-form");
const searchInput = document.querySelector("#search-input");
const searchMessage = document.querySelector("#search-message");
searchForm.addEventListener("submit", (event) => {
event.preventDefault();
const query = searchInput.value.trim();
if (query === "") {
searchMessage.textContent = "Введіть пошуковий запит.";
return;
}
searchMessage.textContent = "";
console.log("Пошуковий запит:", query);
});
</script>Стандартна дія — це автоматична поведінка браузера у відповідь на подію.
event.preventDefault() скасовує стандартну дію події.
Для форм найчастіше потрібно обробляти подію submit.
Для посилань стандартною дією є перехід за адресою з href.
preventDefault() не зупиняє поширення події.
stopPropagation() і preventDefault() мають різне призначення.
event.defaultPrevented показує, чи було скасовано стандартну дію.
Не кожну подію можна скасувати: це можна перевірити через event.cancelable.
Скасовуйте стандартну поведінку лише за потреби та не замінюйте нею правильну HTML-розмітку.