Определение между обновлением и закрытием действий браузера

Когда мы обновляем страницу (F5 или значок в браузере), она сначала вызывает событие ONUNLOAD. Когда мы закрываем браузер (X на правом верхнем значке), он запускает событие ONUNLOAD. Теперь, когда инициируется событие ONUNLOAD, нет возможности различить обновление страницы или закрытие браузера. Если у вас есть какое-либо решение, дайте мне.

15 ответов

Есть решение.

Я хотел отключить пользователя на сервере, когда вкладка или окно браузера были закрыты, но не тогда, когда страница была перезагружена (вы можете различать события перезагрузки / закрытия для другой цели, но вы можете воспользоваться моим решением). Я закончил со следующим процессом, основанным на локальном хранилище HTML5 и клиент-серверном взаимодействии AJAX:

  1. на своей странице, добавьте onunload к window к следующему обработчику (псевдо-javascript):

    function myUnload(event) {
        if (window.localStorage) {
            // flag the page as being unloading
            window.localStorage['myUnloadEventFlag']=new Date().getTime();
        }
    
        // notify the server that we want to disconnect the user in a few seconds (I used 5 seconds)
        askServerToDisconnectUserInAFewSeconds(); // synchronous AJAX call
    }
    
  2. на своей странице, добавьте onloadна body к следующему обработчику (псевдо-javascript):

    function myLoad(event) {
        if (window.localStorage) {
            var t0 = Number(window.localStorage['myUnloadEventFlag']);
            if (isNaN(t0)) t0=0;
            var t1=new Date().getTime();
            var duration=t1-t0;
            if (duration<10*1000) {
                // less than 10 seconds since the previous Unload event => it's a browser reload (so cancel the disconnection request)
                askServerToCancelDisconnectionRequest(); // asynchronous AJAX call
            } else {
                // last unload event was for a tab/window close => do whatever you want (I do nothing here)
            }
        }
    } 
    
  3. на сервере соберите запросы на отключение в списке и установите поток таймера, который проверяет список через регулярные промежутки времени (я использовал каждые 20 секунд). По истечении времени ожидания запроса на отключение (т. Е. 5 секунд прошло) отключите пользователя от сервера. Если за это время получен запрос на отключение, соответствующий запрос на отключение удаляется из списка, чтобы пользователь не был отключен.

Этот подход также применим, если вы хотите провести различие между событием закрытия вкладки / окна и переходом по ссылкам или отправленной форме. Вам просто нужно разместить два обработчика событий на каждой странице, которая содержит ссылки и формы, и на каждой целевой странице ссылки / формы.

Обратите внимание, что я использую unload событие вместо beforeUnload событие для правильного управления ссылками на вложения: когда пользователь нажимает на ссылку на вложение (например, файл PDF), beforeUnload событие отправляется, затем возникает всплывающее окно открытия / сохранения и ничего более (браузер не изменяет отображаемую страницу и не отправляет unload событие). Если бы я использовал beforeUnload событие (как я делал раньше), я бы обнаружил изменение страницы, когда его нет.

Этот подход ограничен браузерами, которые поддерживают локальное хранилище HTML5, поэтому вы, вероятно, будете использовать специальные подходы для старых браузеров, таких как MSIE7.

Другие подходы, основанные на event.clientY не являются надежными, потому что это значение является отрицательным при нажатии на кнопки перезагрузки или закрытия вкладки / окна, и положительным, когда для перезагрузки используются сочетания клавиш (например, F5, Ctrl-R, ...) и закрытие окна (например, Alt-F4), Опора на положение события X также ненадежна, потому что кнопки не размещаются в одной и той же позиции в каждом браузере (например, кнопка закрытия слева).

Может, кто-то еще ищет ответ...

Для этого вы можете использовать SessionStorage! SessionStorage очищается не при перезагрузке страницы, а при закрытии. Таким образом, вы можете установить пару ключ / значение при загрузке страницы, но перед этим вы проверяете, существует ли пара ключ / значение. Если он существует, это означает, что страница была перезагружена, если нет, это означает, что пользователь открыл страницу впервые или в новой вкладке.

if (sessionStorage.getItem('reloaded') != null) {
    console.log('page was reloaded');
} else {
    console.log('page was not reloaded');
}

sessionStorage.setItem('reloaded', 'yes');

Таким образом вы можете doStuff() с onunload событие (пользователь покидает страницу) и otherStuff() если установлена ​​пара ключ / значение (пользователь перезагрузил страницу).

К сожалению, проверка clientY/pageY ценность события, как предлагается в некоторых ответах здесь, не является надежным способом определить, является ли unload Событие запускается вследствие того, что пользователь закрыл страницу.

Причина clientY/pageY Отрицательный, когда вы нажимаете кнопку закрытия браузера, потому что кнопка закрытия расположена над верхней частью документа (то есть выше пикселя 0), но кнопка перезагрузки также означает, что нажатие кнопки перезагрузки также приведет к отрицательному значению для clientY/pageY,

Переход по пути проверки x-координаты события также проблематичен, потому что кнопка закрытия браузера не всегда находится в правой части окна (например, она слева в OS X) и потому что окно может быть закрыто закрыв вкладку или с помощью клавиатуры.

Это большой хак с некоторыми ограничениями, но он будет работать в большинстве практических случаев.

Так что, если вам просто нужно что-то, что работает, когда пользователи используют ctrl+r или cmd+r ярлык, вы можете отслеживать, r нажимается, когда запускается все, что вам нужно сделать при перезагрузке / закрытии.

Просто создать keydown а также keyup прослушиватели событий, которые переключают rDown переменная.

let rDown = false;
window.addEventListener("keydown", event => {
    if (event.key == 'r')
        rDown = true;
})
window.addEventListener("keyup", event => {
    if (event.key == 'r')
        rDown = false;
})

Затем у вас есть прослушиватель событий onunload, в котором функция прослушивателя имеет if заявление, проверяющее, если rDown является true.

window.addEventListener("onunload", () => {
    if (!rDown) {
        // code that only gets run when the window is closed (or
        // some psychopath reloads by actually clicking the icon)
    }
});

К сожалению, пока нет предложенного или надежного способа.

Сегодня у меня возникла та же проблема, и я нашел возможное решение, которым хочу поделиться с вами.

Размышляя о том, что может помочь различить между обновлением и закрытием, мне в голову пришли файлы cookie. Я помню, что установка cookie без явного срока действия делает его доступным только для текущего сеанса. И текущий сеанс явно действителен, пока браузер не будет закрыт. Это не включает закрытие вкладки, но моя проблема была связана с аутентификацией пользователя, и я не хотел выходить из системы только из-за закрытия вкладки (я думаю, что это тот же подход, что и ASPXAUTH файл cookie ASP.NET).

Итак, я положил простое печенье в document.cookies сбор, когда пользователь вошел в систему и проверил его при загрузке страницы: если cookie все еще был там, это было обновление или вновь открывшаяся вкладка, и пользовательские данные сохранялись, если cookie не было, сеанс истек, поэтому пользовательские данные были очищены (аналогично явному выходу из системы)).

Надеюсь, что этот подход может быть полезным для кого-то еще!

Если кто-то все еще ищет это, вот фрагмент, который работал в Chrome.

Я протестирую с другими браузерами и позволю вам, ребята

       $(window).bind('unload', function () {
    if (window.navigator.userActivation.isActive) {
        //refresh
    }
    else {
        //Close
    }
});

Вы можете использовать событие «window: closed» . Он работает во всех основных браузерах. Это не очистит хранилище при обновлении. Только при закрытии вкладки хранилище будет очищено.

Используйте событие window.onbeforeunload для случая, чтобы перейти от страницы, но оно будет включать в себя теги обновления или привязки.... используйте флаг проверки для того же самого, 1 примером для процесса является проверка URL (Initial URL = current URL)) или проверка F5 с использованием ключевого кода для обновления, в случае тегов привязки используйте bind()

Примечание * Код ключа может вызвать проблемы в случае Chrome.

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Test Page</title>

<style type='text/css'>
body {
    font-family: sans-serif;
}
</style>
<script src="jquery-1.9.1.js" type='text/javascript'></script>
<script type='text/javascript'>
var valid=false;
function wireUpEvents() {

if(valid){
alert("Page Refreshed or Redirected");
}else{

window.onbeforeunload = askWhetherToClose;

}
function askWhetherToClose(event) {

if(!valid){

    var msg;

    msg = "You're leaving the page, do you really want to?";
    event = event || window.event;
    event.returnValue = msg;
    return msg;
}}
$(document).bind('keypress', function(e) { 
 if (e.keyCode == 116){ 

 // or you can insert some code to check page refresh
 valid = true; 

//wireUpEvents();
 } 
 }); 
 $("a").bind("click", function() {
//To check redirection using Anchor tags  
 valid = true; 
 //wireUpEvents();
 }); 
 }
$(document).ready(function() { 
 wireUpEvents(); 

 });
</script>
</head>
<body>
<p>Close the browser window, or navigate to <a href="http://stackru.com">Stackru</a></p>
</body>
</html>

Кредит на https://www.anandkanatt.com/how-do-i-detect-browser-window-closed-refreshed/. Я немного упростил его, воспользовавшись для проверки самим открывателем. Проверено в версии Chrome 78.0.3887.7.

Вы можете попробовать это:

  • Добавьте файл refresh-close-Detector.html. Вот пример кода:
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Processing...</title>
</head>
<body>

<script>
  if (this.opener) {
    // the opener was refreshed, do something if you want
  } else {
    // the opener was closed, do something if you want
  }

  // you may want to close the pop up
  this.close()
</script>
</body>
</html>
  • На странице, которую вы хотите определить между действиями обновления и закрытия браузера, добавьте прослушиватель событий для выгрузки:
window.addEventListener('unload', () => {
  open('refresh-close-detector.html', '', 'width=100,height=100');
})
    $(window).bind('unload', function () {
        if (/Firefox[\/\s](\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 4) {
            console.log('firefox delete');
            var data = { async: false };
            endSession(data);
            return null;
        }
        else {
            console.log('NON-firefox delete');
            var data = { async: true };
            endSession(data);
            return null;
        }
    });

    function endSession(data) {
        var id = 0

        if (window) { // closeed
            id=1
        }

        $.ajax({
            url: '/api/commonAPI/'+id+'?Action=ForceEndSession',
            type: "get",
            data: {},
            async: data.async,
            success: function () {
                console.log('Forced End Session');
            }
        });
    }

Используйте if (окно), чтобы определить, закрыто или просто перезагрузить. работает на меня.

Я только что попробовал это, и это решило проблему: создайте объект sessionStorage, который будет уничтожен, когда пользователь закроет браузер. Мы можем проверить объект sessionStorage, чтобы определить, закрыл ли пользователь браузер или обновил страницу (объект sessionStorage не будет уничтожен при обновлении страницы).

Это рабочее решение

export class BootstrapComponent implements OnInit {

  validNavigation = 0;

  constructor(
    private auth: AuthenticationService
  ) { }

  ngOnInit() {
    const self = this;
    self.registerDOMEvents();
  }

  registerDOMEvents() {
    const self = this;
    window.addEventListener('unload', () => {
      if (self.validNavigation === 0) {
        self.endSession();
      }
    });
    document.addEventListener('keydown', (e) => {
      const key = e.which || e.keyCode;
      if (key === 116) {
        self.validNavigation = 1;
      }
    });
  }

  endSession() {
    const self = this;
    self.auth.clearStorage();
  }
}

Мое предыдущее решение работало для меня в IE. window.event не будет определяться для браузеров, отличных от IE, поскольку 'событие' определяется глобально в IE, в отличие от других браузеров. Вам нужно будет указать событие в качестве параметра в случае других браузеров. Также, что clientX не определен для Firefox, мы должны использовать pageX.

Попробуйте что-то вроде этого.... должно работать для IE и Firefox это...

<html>
<body>
<script type="text/javascript">

window.onunload = function(e) {
// Firefox || IE
e = e || window.event;

var y = e.pageY || e.clientY;

if(y < 0)  alert("Window closed");
else alert("Window refreshed");

}
</script>
</body>
</html>
<html>
<body onunload="doUnload()">
<script>
   function doUnload(){
     if (window.event.clientX < 0 && window.event.clientY < 0){
       alert("Window closed");
     }
     else{
       alert("Window refreshed");
     }
   }
</script>
</body>
</html>
Другие вопросы по тегам