При нажатии кнопки «Назад» происходит кроссбраузерная загрузка?

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

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


person Bill    schedule 01.10.2008    source источник
comment
Это не проблема - это позволяет быстро загружать веб-страницу, когда пользователь нажимает кнопку «Назад». Подробности см. В моем ответе ниже. Предлагаемые здесь обходные пути делают веб-страницу более раздражающей для пользователя, поскольку переход назад / вперед выполняется медленнее.   -  person Nickolay    schedule 08.02.2010
comment
@romkyns: ваш комментарий не имеет отношения к этому вопросу. Когда браузеры не восстанавливают состояние JS / DOM, они запускают событие загрузки.   -  person Nickolay    schedule 06.05.2012
comment
Здесь решена кнопка возврата истории iOS 5+ stackoverflow.com/a/12652160/1090395   -  person Mladen Janjetovic    schedule 13.05.2015


Ответы (15)


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

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

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

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

[изменить (Николай): вот почему это работает именно так: 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>
person user123444555621    schedule 14.10.2008
comment
@ Pumbaa80, вы правы - я попробовал это в Firefox 3 и воспроизвел ваши результаты. Странный! - person Jon Schneider; 21.05.2009
comment
Очень хорошо ... хотя это недокументированная функция / ошибка, и она может просто перестать работать в будущих версиях браузера, но это все равно интересно. - person Wadih M.; 01.09.2009
comment
Это тоже работает (не забудьте часть onunload =, иначе не будет работать с ff3): ‹body onload = alert ('onload'); onunload = › - person Wadih M.; 01.09.2009
comment
Это связано с тем, что браузер предполагает, что страница не кэшируется, если у нее есть onunload обработчик (страница уже все уничтожила; зачем ее кэшировать?). - person Casey Chu; 10.05.2010
comment
Два года спустя это все еще продолжается. Меня озадачили несколько дней. Пумба, спасибо за это! - person patrick; 22.11.2010
comment
Ответ, похоже, не работает в современных браузерах - проверено в последних версиях Chrome и Opera - person Andrew; 17.06.2011
comment
@ Андрей: В Opera 11.11 вроде все работает так же, как и раньше. Chrome 12 неожиданно запускает загрузку даже без взлома выгрузки. Есть ли у вас другие результаты? - person user123444555621; 02.08.2011
comment
Pumbaa80 именно то, что я вижу. - person Benjamin Atkin; 10.08.2011
comment
Извините, ребята, я немного запутался, непонятно, что мне делать, просто добавить onunload="" в тег body? это оно? во всех браузерах? Пробовал, и, похоже, не работает ни в Mozilla, ни в Chrome. - person Burjua; 18.08.2011
comment
@Buruja: Совершенно верно. Этому ответу более двух лет, поэтому он может не относиться к некоторым новым браузерам. Однако я только что протестировал Firefox 6 / Mac, и он все еще работает. - person user123444555621; 19.08.2011
comment
На этом закончились 10 часов ненависти к Android. - person Blair Scott; 31.08.2011
comment
не работает в сафари для iPad ... пожалуйста, снимите отметку как ответ - person xus; 08.06.2012
comment
По-прежнему отлично работает для последнего обновления Safari до Yosemite - person egr103; 16.10.2014
comment
Не работает в Safari, по крайней мере, для меня в El Capitan и iOS 10. - person miho; 15.09.2016

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

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

По этой же причине добавление обработчика «unload» останавливает сохранение страницы в bfcache (что замедляет обратный переход) - обработчик выгрузки может выполнять задачи очистки, которые могут оставить страницу в неработоспособном состоянии.

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

Использованная литература:

person Nickolay    schedule 07.02.2010
comment
Это очень круто. В настоящее время я нахожусь в ситуации, когда мои манипуляции с домом не сохраняются в bfcache. Есть ли ситуации, когда вы могли бы этого ожидать? - person Benson; 22.05.2010
comment
@Benson: возможные причины, по которым Firefox не сохраняет вашу страницу в bfcache, перечислены на странице dev.mo, на которую я ссылался. Я не думаю, что можно сохранить страницу в bfcache, но определенное состояние DOM не сохраняется. - person Nickolay; 22.05.2010
comment
Николай, я понимаю ваше нежелание принудительно перезагрузить и отменить хорошую работу, проделанную bfcache, но есть ли другой способ обновить dom страницы в bfcache? Например, рассмотрим ситуацию, когда я перехожу со страницы со списком сообщений к одному из них, и когда я возвращаюсь назад, я хочу, чтобы индикатор прочитанных / непрочитанных изменился. Как это сделать без перезагрузки страницы? - person Greg; 30.08.2010
comment
@Greg: вы имеете в виду, что разработчик контролирует страницу? Запустите запрос ajax от слушателя 'pageshow'. - person Nickolay; 02.09.2010
comment
Есть идеи о том, как использовать jQuery и получить быструю поддержку bfcache? - person Alex Black; 22.11.2010
comment
@Alex Black: по состоянию на февраль 2010 года ответ заключался в использовании новейшего jQuery. Это было проблемой в jQuery 1.3. - person Nickolay; 24.11.2010
comment
@ Nickolay. Спасибо за ваше объяснение. Я сомневаюсь, что событие pageShow (сохраняемое свойство) запускается в IE или chrome. Если да, то пожалуйста, посмотрите stackoverflow.com/questions/6363199/. - person facebook; 16.06.2011
comment
@Nickolay, bfcache полностью глючит, если на веб-сайте используются pushstate и replacestate. Есть ли у нас какие-то подходящие решения, которые действительно работают? - person Pacerier; 12.10.2014
comment
@Pacerier: Я не знаю, но вы могли бы получить лучший ответ, если бы связались с вопросами / отчетами об ошибках, которые привели вас к такому выводу. - person Nickolay; 12.10.2014
comment
Есть ли в Chrome bfcache? Мне удалось запустить bfcache с Safari и FF, но не с Chrome. И другие потоки / блоги предполагают, что Chrome не реализовал bfcache. См., Например, эту проблему Chrome: code.google.com/p/chromium / issues / detail? id = 2879 - person mla; 24.07.2015
comment
мла, спасибо за ссылку! Я написал это, когда Chrome был основан на webkit и ошибочно предположил, что он был автоматически включен в Chrome (в конце концов, это должен быть быстрый браузер!) Обновил сообщение. - person Nickolay; 24.07.2015

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

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

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

Редактировать для полноты

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

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

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

person Brian Heese    schedule 19.02.2010
comment
Куда вы это добавили? И как вы заставили что-нибудь стрелять после того, как пользователь нанес ответный удар? Пожалуйста, покажите нам код! - person Keerigan; 03.04.2012
comment
Что вы имеете в виду, когда говорите мое условное утверждение? - person Phillip Senn; 08.04.2015
comment
@Phillip Условный оператор - это оператор if. - person Brian Heese; 20.04.2015

Хорошо, вот окончательное решение, основанное на исходном решении ckramer и примере palehorse, которое работает во всех браузерах, включая Opera. Если вы установите для history.navigationMode значение «совместимый», тогда функция готовности jQuery будет срабатывать при нажатии кнопки «Назад» в Opera, а также в других основных браузерах.

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

Пример:

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

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

person Bill    schedule 04.10.2008
comment
Очевидно, это было давно (около 5,5 лет), но стоит отметить, что ваша ссылка мертва. - person Jeff; 08.05.2014
comment
У меня это решение не работает. У меня эта проблема в последней версии Firefox (45.0.1) - person Armin; 01.04.2016

Я не мог заставить приведенные выше примеры работать. Я просто хотел запустить обновление определенных измененных областей div при возвращении на страницу с помощью кнопки «Назад». Уловка, которую я использовал, заключалась в том, чтобы установить скрытое поле ввода (называемое «грязным битом») равным 1, как только области div изменились с оригинала. Скрытое поле ввода фактически сохраняет свое значение, когда я нажимаю кнопку "Назад", поэтому при загрузке я могу проверить этот бит. Если он установлен, я обновляю страницу (или просто обновляю 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>

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

person thorie    schedule 31.05.2012
comment
Хотя это не работает в Firefox, я думаю, что это хитрый способ справиться с ситуацией в IE / Chrome, где сохранение скрытого поля очень полезно. Я использовал ваш трюк, а также событие Pageshow, поэтому рассмотрю все основные браузеры. - person Magnus Smith; 05.11.2012
comment
Какой браузер не работает со страницами, как это работает? - person Justin; 29.08.2014

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

person Community    schedule 24.02.2009

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

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

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

person Tom    schedule 16.02.2011

Я могу подтвердить ckramer, что событие готовности jQuery работает в 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>
person palehorse    schedule 01.10.2008

для людей, которые не хотят использовать всю библиотеку jquery, я выделил реализацию в отдельный код. Это всего лишь 0,4 КБ.

Вы можете найти код вместе с учебником по немецкому в этой вики: http://web.archive.org/web/20130417092220/http://www.easy-coding.de/wiki/html-ajax-und-co/onload-event-cross-browser-kompatibler-domcontentloaded.html

person Torben Brodt    schedule 11.09.2010
comment
Одинокая ссылка считается плохим ответом (см. faq), поскольку сама по себе бессмысленна, а целевой ресурс не гарантируется живы в будущем. Желательно включить сюда основные части ответа и предоставить ссылку для справки. - person j0k; 12.05.2014

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

person ckramer    schedule 01.10.2008
comment
Спустя долгое время кажется, что ready не запускается в Firefox при использовании кнопки «Назад». См. Также ответ Николая. - person Arjan; 13.07.2010

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

person Sergey Ilinsky    schedule 01.10.2008

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

person Johann    schedule 10.05.2010

Хорошо, я попробовал это, и он работает в 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>
person Bill    schedule 01.10.2008

Событие разгрузки не работает нормально в IE 9. Я пробовал его с событием загрузки (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>
person mallesham    schedule 07.08.2011

Я использовал шаблон html. В файле custom.js этого шаблона была такая функция:

    jQuery(document).ready(function($) {

       $(window).on('load', function() {
          //...
       });

    });

Но эта функция не работала, когда я возвращался после перехода на другую страницу.

Итак, я попробовал это, и это сработало:

    jQuery(document).ready(function($) {
       //...
    });

   //Window Load Start
   window.addEventListener('load', function() {
       jQuery(document).ready(function($) {
          //...
       });
   });

Теперь у меня есть две "готовые" функции, но они не выдают ошибок, и страница работает очень хорошо.

Тем не менее, я должен заявить, что он тестировался в Windows 10 - Opera v53 и Edge v42, но не в других браузерах. Имейте в виду это ...

Примечание: версия jquery была 3.3.1, а версия миграции была 3.0.0.

person bafsar    schedule 01.07.2018