Событие 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 только в тех случаях, когда это улучшает пользовательский опыт. Например, защита от потери данных при случайном свайпе — это хорошо, в то время как беспорядочные попытки удержать лишь надоедают и вызывают ассоциации с мошенническими сайтами.