Клавиша / esc

beforeunload

Событие ухода пользователя со страницы.

Время чтения: меньше 5 мин

Кратко

Скопировано

Когда пользователь уходит со страницы, мы можем спросить его, точно ли он хочет уйти. За это отвечает обработка события beforeunload.

Событие происходит перед событием выгрузки страницы unload.

Как пишется

Скопировано
        
          
          window.addEventListener('beforeunload', function () {  // ...})
          window.addEventListener('beforeunload', function () {
  // ...
})

        
        
          
        
      

Как понять

Скопировано

Мы все хотя бы раз теряли проделанную работу по какой-либо причине:

  1. Нетленная классика с зависшим Word и несохранённой курсовой.
  2. Случайный свайп влево на ноутбуках Apple, который вместо горизонтальной прокрутки возвращает на предыдущую страницу.
  3. Автор этих строк однажды перепутал git stash pop с git stash drop 😰

Есть страницы, на которых выполняется некоторая работа. Если эта работа не сохраняется, например, в localStorage, стоит защитить пользователя от фрустрации при возможной потере. В этом нам поможет обработка события beforeunload.

Обработка с помощью addEventListener():

        
          
          window.addEventListener('beforeunload', function (event) {  // Отменяем поведение по умолчанию  event.preventDefault()  // Chrome требует наличия returnValue  event.returnValue = ''})
          window.addEventListener('beforeunload', function (event) {
  // Отменяем поведение по умолчанию
  event.preventDefault()

  // Chrome требует наличия returnValue
  event.returnValue = ''
})

        
        
          
        
      

Обработка через определение onbeforeunload на объекте window:

        
          
          window.onbeforeunload = () => false
          window.onbeforeunload = () => false

        
        
          
        
      

Во втором случае необязательно возвращать false, можно вернуть любое значение, кроме null и undefined. Раньше браузеры использовали возвращаемое значение в качестве сообщения, но в современной спецификации данное поведение изменили. Встречали сайты, которые при попытке закрыть страницу показывали сообщения про нигерийских родственников или правоохранительные органы? Потому и изменили.

При обработке этого события браузер покажет всплывающее окно, в котором нужно будет подтвердить своё намерение покинуть страницу. В Яндекс Браузере, например, оно выглядит так:

Всплывающее окно браузера, появляющееся при обработке beforeunload. Содержит вопрос «Хотите покинуть страницу» и две кнопки «да» и «отменить».

Как оно выглядит в вашем браузере можно проверить с помощью демо ниже.

Открыть демо в новой вкладке

На практике

Скопировано

Антон Субботин советует

Скопировано

🛠 Как бы это очевидно ни звучало, помните, что обработка beforeunload может отменить уход со страницы. На одном из проектов это использовалось для предотвращения случайного выхода со страницы с анкетой. При этом редирект с этой страницы превращал её в кирпич. Видели когда-то такой код: document.body.innerHTML = document.body.innerHTML? Он пересоздаёт страницу из строки. Внешне ничего не меняется, но страница перестаёт быть интерактивной, так как обработчики не воссоздаются, чтобы в момент перехода нельзя было ввести новую информацию или отправить невалидный запрос. Получался сценарий:

  • Пользователь пытается уйти со страницы.
  • Страница превращается в тыкву.
  • Пользователь отменяет переход и остаётся на окирпиченной странице.

Такие баги довольно сложно дебажить, поэтому будьте аккуратны и просчитывайте все пользовательские сценарии. Более конкретно: не используйте событие beforeunload для модификации DOM-дерева. Оно нужно не для этого.

🛠 Обрабатывайте beforeunload только в тех случаях, когда это улучшает пользовательский опыт. Например, защита от потери данных при случайном свайпе — это хорошо, в то время как беспорядочные попытки удержать лишь надоедают и вызывают ассоциации с мошенническими сайтами.