Skip to main content

Подія beforeunload

beforeunload це подія, яка спрацьовує перед вивантаженням (unload) поточної сторінки з пам'яті браузера. Вона виникає, коли користувач закриває вкладку чи вікно, перезавантажує сторінку або переходить за посиланням чи вводить новий URL.

Теорія

TL;DR

  • Слухається на window, спрацьовує перед вивантаженням сторінки.
  • event.preventDefault() разом із event.returnValue = '' показує стандартний діалог підтвердження виходу.
  • Власний текст діалогу задати не можна, браузери його ігнорують.
  • Діалог варто показувати лише тоді, коли справді є незбережені зміни.
  • Асинхронні дії (fetch, таймери) тут не встигають; синхронний запис у localStorage встигає.
  • beforeunload можна скасувати, unload уже ні.

Швидкий приклад

javascript
window.addEventListener('beforeunload', (event) => { event.preventDefault(); event.returnValue = ''; // обов'язково! });

Після цього браузер покаже діалог підтвердження виходу:

Ви справді хочете покинути сторінку? Введені дані можуть бути втрачені.

Важливо:

  • Сучасні браузери не дозволяють задавати свій текст у цьому вікні. Раніше можна було написати event.returnValue = 'Ви впевнені?', але тепер це ігнорується.
  • Так зроблено заради безпеки та UX, щоб сайти не могли тиснути на користувача повідомленнями на кшталт «залишайтеся з нами».

Коли використовувати

Використовується, якщо користувач може втратити незбережені зміни, наприклад:

  • редагує текст, але не натиснув «Зберегти»;
  • заповнює форму;
  • пише коментар;
  • робить щось у застосунку з незбереженим станом.
javascript
let formChanged = false; document.querySelector('form').addEventListener('input', () => { formChanged = true; }); window.addEventListener('beforeunload', (e) => { if (formChanged) { e.preventDefault(); e.returnValue = ''; } });

Тепер, якщо користувач змінив форму і намагається піти, з'явиться попередження.

Тихий hook перед виходом, без діалогу

Якщо треба просто виконати очищення або якусь логіку перед вивантаженням, без діалогу:

javascript
window.addEventListener('beforeunload', () => { localStorage.setItem('lastVisited', new Date().toISOString()); });

Ця подія, остання точка, де можна зберегти дані в localStorage або sessionStorage.

Різниця між beforeunload і unload

ПодіяКоли спрацьовуєЧи можна зупинити вихідКоли використовувати
beforeunloadПеред вивантаженнямТак, через preventDefault()Попередження про незбережені дані
unloadПісля початку вивантаженняНіОчищення, аналітика, логування

Обмеження

  • Не можна використовувати alert() або confirm() всередині beforeunload, браузери їх блокують.
  • Не варто запускати асинхронні операції (запити, fetch), вони не встигнуть завершитися. Для аналітики є navigator.sendBeacon().
  • Працює лише у вікні або вкладці браузера, а не у фреймах.
  • Краще не вішати без потреби, це UX-спам. Багато браузерів взагалі не покажуть діалог, якщо користувач ще не взаємодіяв зі сторінкою.

Підсумок

Що робитьПодія beforeunload
Коли спрацьовуєПеред тим, як користувач покине сторінку
Для чого потрібнаПопередити про втрату незбережених даних
Як зупинити вихідevent.preventDefault() плюс event.returnValue = ''
Свій текстНе можна, браузер покаже стандартний
Коли не підходитьДля асинхронних дій, вони не встигнуть виконатися

Запам'ятати просто: beforeunload це «останній шанс» сказати браузеру: «Стій! У користувача є незбережені дані.»

Типові помилки

  • Вішати обробник безумовно. Діалог на кожному виході дратує і нічого не захищає. Ставте прапорець «є незбережені зміни» і перевіряйте його всередині обробника.
  • Забувати event.returnValue = ''. У частині браузерів самого preventDefault() мало, і діалог просто не з'явиться.
  • Розраховувати на власний текст. Рядок, повернутий з обробника або записаний у returnValue, більше ніде не показується.
  • Слати аналітику через fetch. Запит обірветься разом зі сторінкою. Для цього існує navigator.sendBeacon(), який браузер доставить уже після вивантаження.
  • Не знімати обробник після збереження. Після успішного submit треба скинути прапорець або викликати removeEventListener, інакше користувач побачить попередження вже після того, як дані збережено.
  • Покладатися на unload. Він не гарантовано спрацьовує на мобільних і ламає bfcache, тому кеш назад та вперед перестає працювати. Для збереження стану надійніше слухати visibilitychange зі станом hidden.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.