При нажатии кнопки «Назад» происходит событие кросс-браузерной загрузки? - PullRequest
177 голосов
/ 01 октября 2008

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

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

Ответы [ 15 ]

112 голосов
/ 14 октября 2008

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

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

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

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

[ edit (Николай) : вот почему это работает так: 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>
72 голосов
/ 08 февраля 2010

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

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

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

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

Ссылки:

31 голосов
/ 19 февраля 2010

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

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

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

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

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

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

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

21 голосов
/ 04 октября 2008

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

Эта страница содержит дополнительную информацию .

Пример:

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

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

6 голосов
/ 01 июня 2012

Я не смог заставить работать приведенные выше примеры. Я просто хотел вызвать обновление определенных измененных областей 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>

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

4 голосов
/ 16 февраля 2011

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

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

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

4 голосов
/ 11 сентября 2010

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

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

4 голосов
/ 24 февраля 2009

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

4 голосов
/ 01 октября 2008

Я могу подтвердить 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>
3 голосов
/ 01 октября 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...