После возвращения в историю Firefox JavaScript не запускается

84

Когда я использую кнопку «Назад» в Firefox для перехода на ранее посещенную страницу, скрипты на этой странице больше не запускаются .

Есть ли какое-либо исправление / обходной путь для повторного выполнения скриптов при просмотре страницы во второй раз?

Обратите внимание, что я протестировал одни и те же страницы в Google Chrome и Internet Explorer, и они работают должным образом.


Вот файлы и шаги, которые я использовал для проверки проблемы:

(перейдите к 0.html, щелкните, чтобы перейти к 1.html, кнопка "Назад")

0.html

<html><body>
<script>
  window.onload = function() { alert('window.onload alert'); };
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

1.html

<html><body>
<p>Go BACK!</p>
</body></html>
Патонца
источник

Ответы:

93

Установите пустую функцию для вызова в window.onunload:

window.onunload = function(){}; 

например

<html><body>
<script type="text/javascript">
  window.onload = function() { alert('window.onload alert'); };
  window.onunload = function(){};
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

Источник: http://www.firefoxanswer.com/firefox/672-firefoxanswer.html (заархивированная версия)

Джон Бабер-Лусеро
источник
2
Спасибо, это работает. Любой намек на то, что делает обработчик onunload по умолчанию? (например, я здесь переопределяю какое-то поведение по умолчанию?)
Патонза,
Хорошо, спасибо, я займусь расследованием. Еще раз спасибо, эта проблема преследует меня какое-то время :)
Patonza
Кто-нибудь знает, зачем FireFox это нужно, а другим браузерам - нет?
Пим Ягер
7
Вы ничего не переопределяете, это просто не позволяет Firefox кэшировать страницу в обратном кэше (bfcache). developer.mozilla.org/en/DOM/window.onunload developer.mozilla.org/En/Using_Firefox_1.5_caching
Крис Хаас,
1
Хотя он должен сломать bfcache, к сожалению, кажется, что он все еще помнит предыдущую страницу - в частности, загруженные URL-адреса iframe загружаются снова, когда вы возвращаетесь, и если сгенерированный контент необходимо поместить во фрейм, похоже, что кроссбраузер не работает способ обновить это заново.
NoBugs
76

Когда я использую кнопку «Назад» в Firefox для перехода на ранее посещенную страницу, скрипты на этой странице больше не запускаются.

Это правильно, и это хорошо.

Когда вы нажимаете ссылку в Firefox (и Safari, и Opera), она не сразу уничтожает вашу страницу, чтобы перейти на следующую. Он сохраняет страницу нетронутой, просто скрывая ее от просмотра. Если вы нажмете кнопку «Назад», она вернет старую страницу обратно в представление, без необходимости загружать документ снова; это намного быстрее, что приводит к более плавному переходу между страницами вперед / назад для пользователя.

Эта функция называется bfcache .

Любой контент, который вы добавили на страницу во время предыдущей загрузки и использования пользователем, останется там. Любые обработчики событий, которые вы прикрепили к элементам страницы, по-прежнему будут прикреплены. Любые установленные вами тайм-ауты / интервалы по-прежнему будут активны. Поэтому редко возникает необходимость знать, что вас спрятали и снова показали. Было бы неправильно вызывать onloadили встраивать код скрипта снова, потому что любые привязки и генерация контента, которые вы выполняли в этой функции, будут выполняться второй раз для того же контента с потенциально катастрофическими результатами. (например, document.writeвстроенный скрипт полностью уничтожит страницу.)

Причина, по которой запись в window.onunloadимеет эффект, заключается в том, что браузеры, реализующие bfcache, решили, что - для совместимости со страницами, которым действительно нужно знать, когда они удаляются, - любая страница, которая заявляет о своем интересе узнать, когда onunloadпроисходит, приведет к тому, что bfcache будет быть отключенным. Эта страница будет загружена заново, когда вы вернетесь к ней, а не будет загружена из bfcache.

Итак, если вы установите window.onunload= function() {};, то на самом деле вы намеренно нарушаете bfcache. Это приведет к тому, что ваши страницы будут медленно перемещаться, и не должны использоваться, кроме как в крайнем случае.

Если вам действительно нужно знать, когда пользователь уходит или возвращается на вашу страницу, не нарушая bfcache, вы можете вместо этого перехватить события onpageshowи onpagehide:

window.onload=window.onpageshow= function() {
    alert('Hello!');
};
бобинс
источник
4
Моя проблема в том, что bfcache не кеширует ВСЮ страницу, поэтому мне приходится повторно запускать js, чтобы восстановить потерянный контент. Так что перебить всю страницу можно. В любом случае, я не использую событие window.onload, я использую событие jQuery document.ready. Знаете ли вы, как можно использовать document.ready и избежать этой проблемы?
Patonza
bfcache, как правило, должен возвращать всю страницу в том виде, в котором она была оставлена. Какого контента не хватает после возврата с предыдущей страницы? (тестовый пример?) document.readyбудет работать по сути так же, как window.onload(для некоторых браузеров они все равно являются одним и тем же событием).
bobince
14
Это НЕ хорошо, потому что он не запускает javascript снова, учитывая, что он кэширован ... но на самом деле НЕ кэширует изменения, сделанные javascript ранее. Если javascript исчезает в элементе при загрузке страницы, он не исчезает снова при посещении в истории ... но ДЕЙСТВИТЕЛЬНО запускает его снова с 0 непрозрачностью, отменяя то, что сделал javascript! Это должно быть ВСЕ ИЛИ НИЧЕГО. Вы должны кэшировать полное состояние страницы после запуска javascript, если вы хотите представить его в кэше без повторного запуска javascript!
Джимбо Джонни
1
@ Джимбо: Тестовый пример, пожалуйста. bfcache предназначен (и во всех случаях, которые я когда-либо видел) сохраняет точное состояние DOM поверх скрытия / показа. Элемент, который был затенен, останется непрозрачным при возврате страницы, если только не будет запущен какой-либо другой скрипт, чтобы скрыть его снова.
bob с
1
@bobince - Создайте элемент с файлом CSS, устанавливая непрозрачность на ноль, а затем используйте jQuery, чтобы он исчез в готовом документе. Вернувшись в историю, он повторно применит CSS таблицы стилей (ноль) без сохранения непрозрачности: 1, которую JS добавил к атрибуту стиля при его постепенном появлении. При первом посещении страницы элемент будет постепенно увеличиваться от нуля до 1. Перейдите на другую страницу и нажмите обратно, и он просто останется полностью прозрачным.
Джимбо Джонни
24

Вы можете проверить persistedсвойство pageshowсобытия. При начальной загрузке страницы установлено значение false. Когда страница загружается из кеша, ей присваивается значение true.

window.onpageshow = function(event) {
    if (event.persisted) {
        alert("From bfcache");
    }
};

По какой-то причине jQuery не имеет этого свойства в событии. Вы можете найти его в оригинальном событии.

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        alert("From bfcache");
    }
});
Мика Туупола
источник
Спасибо за предоставленные версии javascript и jquery! Вы пропустили закрывающую скобку в конце (это не стон!). Я также отмечу, ради других, что отчет IE и Chrome .persisted всегда ложен, независимо от того.
Магнус Смит
Как заметил Магнус, у меня это не работало в Chrome, пока я не удалил оператор if.
Джастин
У меня это сработало в Chrome 58.0.3029.110 (64-разрядная версия) и FF 53.0.2 (64-разрядная версия) без каких-либо изменений.
kmoser
1

Подключитесь к событию onunload, которое ничего не делает:

<html><body>
<script type="text/javascript">
  window.onload = function() { alert('window.onload alert'); };
  window.onunload = function(){}; 
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>
Крис Хаас
источник
Не уверен, я проголосовал «за», похоже, кто-то только что проголосовал «против» за каждый ответ на этот вопрос ...
Патонза,
вы должны добавить к своему ответу, что добавление события onunload на вашу страницу фактически отключит кэширование страницы полностью. Это не просто заставит JS снова запуститься, но и повысит нагрузку на сервер. На самом деле это предложение не следует относиться легкомысленно, это следует тщательно продумать.
dreagan
@dreagan, это отключает bfcache, но не обязательно кеш HTTP. Кэш HTTP имеет совершенно другой набор правил. Если вы включите там сон на стороне сервера, вы должны заметить это во время возврата. Mozilla говорит об этом в своем третьем вопросе в FAQ по BFCache .
Крис Хаас,
Я говорил о BFcache, надо было это указать. Это не означает, что вы должны выдавать подобное предложение, не уведомляя OP о последствиях. Альтернативой может быть использование события onpopstate, чтобы снова запустить javascript.
dreagan
Я все еще не знаю, понимаю ли я. Почему «нагрузка на сервер повысится на ступеньку выше», если клиентский локальный bfcache будет обойден? Да, DOM необходимо будет перестроить, но HTML должен быть частью HTTP-кеша клиента. Да, необходимо будет перезагрузить дополнительные ресурсы, но они также должны быть частью клиентского HTTP-кеша. Что касается onpopstate, когда этот вопрос был задан почти пять лет назад, это событие было все еще относительно новым, а поддержка браузерами была очень непоследовательной
Крис Хаас,
1

Насколько я знаю, Firefox не запускает onLoadсобытие на спине.

Вместо этого он должен запускать onFocus на основе этой ссылки здесь .

systempuntoout
источник
Протестировал его, и windows.onfocus действительно вызывается, даже без установки пустого обработчика window.onunload. Установка onunload - это немного более приятный способ обхода, но .onfocus тоже подойдет. Спасибо :)
Patonza
1

Простой способ заставить страницу выполнять JavaScript, когда пользователь возвращается к ней с помощью истории браузера, - это событие OnPopState. Мы используем это, чтобы приостановить и воспроизвести видео на нашей домашней странице ( https://fynydd.com ).

window.onpopstate = function() {

    // Do stuff here...
};
Майкл А.
источник
0

для некоторых случаев, таких как прослушиватель изменения URL-адреса операций ajax, может использоваться

$(window).on('hashchange', function() {
        ....
});
Укротитель
источник