Есть ли кросс-браузерное событие onload при нажатии кнопки "Назад"?

Для всех основных браузеров (кроме IE) событие JavaScript onload не срабатывает, когда страница загружается в результате операции с кнопкой "Назад" - она ​​запускается только при первой загрузке страницы.

Может ли кто-нибудь указать мне на какой-то примерный кросс-браузерный код (Firefox, Opera, Safari, IE,...), который решает эту проблему? Я знаком с событием Firefox pageshow, но, к сожалению, ни Opera, ни Safari не реализуют это.

Ответы

Ответ 1

Ребята, я обнаружил, что JQuery имеет только один эффект: страница перезагружается при нажатии кнопки "Назад". Это не имеет ничего общего с готовым.

Как это работает? Ну, JQuery добавляет прослушиватель событий onunload.

// http://code.jquery.com/jquery-latest.js
jQuery(window).bind("unload", function() { // ...

По умолчанию он ничего не делает. Но почему-то это, похоже, вызывает перезагрузку в Safari, Opera и Mozilla - независимо от того, что содержит обработчик событий.

[edit (Nickolay): вот почему это работает так: webkit.org, developer.mozilla.org. Прочитайте эти статьи (или мое резюме в отдельном ответе ниже) и подумайте, действительно ли вам нужно сделать это и сделать загрузку страницы медленнее для ваших пользователей.]

Не могу в это поверить? Попробуйте следующее:

<body onunload=""><!-- This does the trick -->
<script type="text/javascript">
    alert('first load / reload');
    window.onload = function(){alert('onload')};
</script>
<a href="http://stackoverflow.com">click me, then press the back button</a>
</body>

Вы увидите похожие результаты при использовании JQuery.

Вы можете сравнить с этим без onunload

<body><!-- Will not reload on back button -->
<script type="text/javascript">
    alert('first load / reload');
    window.onload = function(){alert('onload')};
</script>
<a href="http://stackoverflow.com">click me, then press the back button</a>
</body>

Ответ 2

Некоторые современные браузеры (Firefox, Safari и Opera, но не Chrome) поддерживают специальный кеш "назад/вперед" (я буду называть его bfcache, который является термином, изобретенным Mozilla), который задействуется, когда пользователь переводит Назад, В отличие от обычного (HTTP) кэша, он фиксирует полное состояние страницы (включая состояние JS, DOM). Это позволяет ему повторно загружать страницу быстрее и точно так же, как пользователь ее оставил.

Событие load не должно срабатывать, когда страница загружается из этого bfcache. Например, если вы создали свой пользовательский интерфейс в обработчике "load", а событие "load" было запущено один раз при начальной загрузке, а во второй раз, когда страница была повторно загружена из bfcache, страница закончилась бы с дублировать элементы пользовательского интерфейса.

Это также связано с тем, что добавление обработчика "разгрузки" останавливает сохранение страницы в bfcache (что замедляет перемещение назад) - обработчик выгрузки может выполнять задачи очистки, которые могут оставить страницу в нерабочее состояние.

Для страниц, которые необходимо знать, когда они перемещаются в/обратно, Firefox 1.5+ и версия Safari с исправлением для ошибка 28758 поддерживают специальные события, называемые "страницами" и "страница".

Литература:

Ответ 3

Я столкнулся с проблемой, что мои js не выполнялись, когда пользователь нажал кнопку "Назад" или "Переслать". Сначала я решил отключить браузер от кеширования, но это, похоже, не проблема. Мой javascript был настроен на выполнение после загрузки всех библиотек и т.д. Я проверил их с событием readyStateChange.

После некоторого тестирования я узнал, что readyState элемента на странице, на которую было нажата ссылка, не "загружен", а "завершен". Добавление || element.readyState == 'complete' к моему условному выражению разрешило мои проблемы.

Просто подумал, что я поделюсь своими выводами, надеюсь, они помогут кому-то другому.

Изменить полноту

Мой код выглядел следующим образом:

script.onreadystatechange(function(){ 
   if(script.readyState == 'loaded' || script.readyState == 'complete') {
      // call code to execute here.
   } 
});

В примере кода выше переменная script была вновь созданным элементом script, который был добавлен в DOM.

Ответ 4

ОК, вот окончательное решение, основанное на начальном решении ckramer и примере palehorse, который работает во всех браузерах, включая Opera. Если вы установите history.navigationMode на "совместимый", тогда функция jQuery ready будет запускаться в операциях Back Button в Opera, а также в других основных браузерах.

На этой странице дополнительная информация.

Пример:

history.navigationMode = 'compatible';
$(document).ready(function(){
  alert('test');
});

Я тестировал это в Opera 9.5, IE7, FF3 и Safari, и он работает во всех них.

Ответ 5

Я не мог заставить приведенные выше примеры работать. Я просто хотел вызвать обновление некоторых модифицированных областей div при возврате на страницу с помощью кнопки "Назад". Трюк, который я использовал, заключался в том, чтобы установить скрытое поле ввода (называемое "грязным битом" ) на 1, как только области div изменились с оригинала. Скрытое поле ввода фактически сохраняет свое значение, когда я нажимаю на него, поэтому onload я могу проверить этот бит. Если он установлен, я обновляю страницу (или просто обновляю div). Однако при исходной загрузке бит не установлен, поэтому я не трачу время на загрузку страницы дважды.

<input type='hidden' id='dirty'>

<script>
$(document).ready(function() {
  if ($('#dirty').val()) {
    // ... reload the page or specific divs only
  }
  // when something modifies a div that needs to be refreshed, set dirty=1
  $('#dirty').val('1');
});
</script>

И он срабатывает должным образом всякий раз, когда я нажимаю кнопку "Назад".

Ответ 6

Я могу подтвердить ckramer, что событие jQuery ready работает в IE и FireFox. Здесь образец:

<html>
<head>
    <title>Test Page</title>
    <script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
    <script type="text/javascript">
            $(document).ready(function () {
               var d = new Date();
               $('#test').html( "Hi at " + d.toString() );
            });
    </script>
</head>
<body>
    <div id="test"></div>
    <div>
        <a href="http://www.google.com">Go!</a>
    </div>
</body>
</html>

Ответ 7

Если я правильно помню, то добавление события unload() означает, что страница не может быть кэширована (в кеше вперёд/назад) - потому что она изменяет состояние или может меняться при прохождении пользователя. Таким образом - небезопасно восстанавливать состояние последней секунды страницы при возврате к ней путем навигации по объекту истории.

Ответ 9

Я думал, что это будет для "onunload", а не загрузки страницы, так как мы не говорим об увольнении какого-либо события при нажатии "Назад"? $document.ready() предназначен для событий, желаемых при загрузке страницы, независимо от того, как вы попадаете на эту страницу (например, перенаправление, открытие браузера прямо на URL и т.д.), а не при нажатии "Назад", если вы не говорите о том, как стрелять на предыдущей странице, когда она загружается снова. И я не уверен, что страница не кэшируется, поскольку я обнаружил, что Javascripts все еще есть, даже если в них включен $document.ready(). Нам пришлось ударить Ctrl + F5 при редактировании наших скриптов, которые имеют это событие, когда мы их пересматриваем, и мы хотим проверить результаты на наших страницах.

$(window).unload(function(){ alert('do unload stuff here'); }); 

- это то, что вам нужно для события onunload, когда вы нажимаете "Назад" и выгружаете текущую страницу, а также запускаете, когда пользователь закрывает окно браузера. Это звучало скорее как то, что было желательным, даже если меня превосхоло число с комментариями $document.ready(). В основном разница между запуском события на текущей странице при ее закрытии или на той, которая загружается при нажатии "Назад" при загрузке. Протестировано в IE 7 отлично, не может говорить для других браузеров, поскольку они не разрешены, где мы находимся. Но это может быть другой вариант.

Ответ 10

jQuery ready было создано событие для такого рода проблемы. Вы можете захотеть вникать в реализацию, чтобы увидеть, что происходит под обложками.

Ответ 11

Билл, я смею ответить на ваш вопрос, однако я не уверен на 100% с моими догадками. Я думаю, что другие браузеры IE при приеме пользователя на страницу в истории не только загружают страницу и ее ресурсы из кеша, но также восстанавливают для нее все состояние DOM (чтение сеанса). IE не выполняет восстановление DOM (или в лизинге не было), и поэтому событие onload выглядит необходимым для правильной переинициализации страницы там.

Ответ 12

Я попробовал решение от Билла, используя $(document).ready... но сначала это не сработало. Я обнаружил, что если script помещается после раздела html, это не сработает. Если это раздел главы, он будет работать, но только в IE. script не работает в Firefox.

Ответ 13

ОК, я пробовал это, и он работает в Firefox 3, Safari 3.1.1 и IE7, но не в Opera 9.52.
Если вы используете пример, показанный ниже (на основе примера palehorse), вы получаете всплывающее окно с предупреждением, когда страница сначала загружается. Но если вы перейдете к другому URL-адресу, а затем нажмите кнопку "Назад", чтобы вернуться на эту страницу, вы не получите всплывающее окно оповещения в Opera (но вы делаете это в других браузерах).

В любом случае, я думаю, что сейчас это достаточно близко. Спасибо всем!

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<meta http-equiv="expires" content="0">
<script src="jquery.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready( 
                    function(){
                      alert('test');
                    }
                 );
</script>
</head>
<body>
<h1>Test of the page load event and the Back button using jQuery</h1>
</body>
</html>

Ответ 14

Событие Unload не работает нормально в IE 9. Я попробовал его с событием load (onload()), он отлично работает на IE 9 и FF5.

Пример:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
    jQuery(window).bind("load", function() {
        $("[name=customerName]").val('');
    });
</script>
</head>
<body>
    <h1>body.jsp</h1>
    <form action="success.jsp">
        <div id="myDiv">

        Your Full Name: <input name="yourName" id="fullName"
            value="Your Full Name" /><br> <br> <input type="submit"><br>

        </div>

    </form>
</body>
</html>