Этот вопрос похож на « Отслеживать, когда пользователь нажимает кнопку возврата» в браузере , но не такой же ... У меня есть решение, и я публикую его здесь для справки и обратной связи. Если у кого-то есть варианты получше, я весь в уши!
Ситуация такова, что у меня есть страница с «редактированием на месте», а-ля flickr. Т.е. есть DIV "нажмите здесь, чтобы добавить описание", который при нажатии превращается в ТЕКСТАР с кнопками Сохранить и Отменить. Нажатие кнопки «Сохранить» отправляет данные на сервер для обновления базы данных и помещает новое описание в DIV вместо TEXTAREA. Если страница обновляется, новое описание отображается из базы данных с опцией «щелкните для редактирования». В наши дни это довольно стандартная штука для Web 2.0.
Проблема в том, что если:
- страница загружается без описания
- описание добавлено пользователем
- переход на страницу осуществляется щелчком по ссылке
- пользователь нажимает кнопку возврата
Затем отображается (из кеша браузера) версия страницы без динамически измененного DIV, содержащего новое описание.
Это довольно большая проблема, поскольку пользователь предполагает, что их обновление было потеряно, и не обязательно понимает, что им нужно обновить страницу, чтобы увидеть изменения.
Итак, возникает вопрос: как вы можете пометить страницу как измененную после ее загрузки, а затем определить, когда пользователь «возвращается к ней», и принудительно выполнить обновление в этой ситуации?
Ответы:
Используйте скрытую форму. Данные формы сохраняются (обычно) в браузерах, когда вы перезагружаете или нажимаете кнопку «Назад» для возврата на страницу. На вашей странице (вероятно, внизу) будет следующее:
<form name="ignore_me"> <input type="hidden" id="page_is_dirty" name="page_is_dirty" value="0" /> </form>
В вашем javascript вам понадобится следующее:
var dirty_bit = document.getElementById('page_is_dirty'); if (dirty_bit.value == '1') window.location.reload(); function mark_page_dirty() { dirty_bit.value = '1'; }
Js, который обнюхивает форму, должен выполняться после того, как HTML полностью проанализирован, но вы можете поместить как форму, так и js в строку вверху страницы (секунда js), если задержка пользователя вызывает серьезную озабоченность.
источник
Вот очень простое современное решение этой старой проблемы.
if (window.performance && window.performance.navigation.type === window.performance.navigation.TYPE_BACK_FORWARD) { alert('Got here using the browser "Back" or "Forward" button.'); }
window.performance в настоящее время поддерживается всеми основными браузерами.
источник
window.performance && window.performance.navigation.type
а не простоwindow.performance.navigation.TYPE_BACK_FORWARD
?).window.performance.navigation.TYPE_BACK_FORWARD
- константа, которая всегда равна 2. Поэтому она используется только для сравнения.performance.navigation
это устарело, и вместо этого предлагается использовать developer.mozilla.org/en-US/docs/Web/API/…2
при нажатии кнопки «Назад». До v70 возвращал некорректно1
.Эта статья объясняет это. См. Код ниже: http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/
<html> <head> <script> function pageShown(evt){ if (evt.persisted) { alert("pageshow event handler called. The page was just restored from the Page Cache (eg. From the Back button."); } else { alert("pageshow event handler called for the initial load. This is the same as the load event."); } } function pageHidden(evt){ if (evt.persisted) { alert("pagehide event handler called. The page was suspended and placed into the Page Cache."); } else { alert("pagehide event handler called for page destruction. This is the same as the unload event."); } } window.addEventListener("pageshow", pageShown, false); window.addEventListener("pagehide", pageHidden, false); </script> </head> <body> <a href="http://www.webkit.org/">Click for WebKit</a> </body> </html>
источник
event.persisted
=false
, даже при нажатии кнопки возврата. Вы должны использоватьwindow.performance.navigation
или PerformanceNavigationTiming для Chrome.Для современных браузеров сейчас это кажется правильным:
const perfEntries = performance.getEntriesByType('navigation'); if (perfEntries.length && perfEntries[0].type === 'back_forward') { console.log('User got here from Back or Forward button.'); }
По состоянию на январь 2020 года это все еще "экспериментальное", но, похоже, поддерживается хорошо.
https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming
источник
Как упоминалось выше, я нашел решение и публикую его здесь для справки и обратной связи.
Первый этап решения - добавить на страницу следующее:
<!-- at the top of the content page --> <IFRAME id="page_is_fresh" src="fresh.html" style="display:none;"></IFRAME> <SCRIPT style="text/javascript"> function reload_stale_page() { location.reload(); } </SCRIPT>
Содержание
fresh.html
не имеет значения, поэтому достаточно следующего:<!-- fresh.html --> <HTML><BODY></BODY></HTML>
Когда код на стороне клиента обновляет страницу, он должен пометить модификацию следующим образом:
function trigger_reload_if_user_clicks_back_button() { // "dis-arm" the reload stale page function so it doesn't fire // until the page is reloaded from the browser's cache window.reload_stale_page = function(){}; // change the IFRAME to point to a page that will reload the // page when it loads document.getElementById("page_is_fresh").src = "stale.html"; }
stale.html
выполняет всю работу: при загрузке он вызываетreload_stale_page
функцию, которая при необходимости обновляет страницу. При первой загрузке (то есть после внесения измененийreload_stale_page
функция ничего не сделает).<!-- stale.html --> <HTML><BODY> <SCRIPT type="text/javascript">window.parent.reload_stale_page();</SCRIPT> </BODY></HTML>
Судя по моему (минимальному) тестированию на этом этапе, похоже, что это работает так, как хотелось. Я что-нибудь упустил?
источник
Вы можете решить эту проблему с помощью события onbeforeunload :
window.onbeforeunload = function () { }
Наличие пустой функции диспетчера событий onbeforeunload означает, что страница будет перестраиваться при каждом доступе к ней. Javascripts будет повторно запущен, серверные скрипты будут повторно запущены, страница будет построена так, как если бы пользователь нажал на нее в первый раз, даже если пользователь попал на страницу, просто нажав кнопку назад или вперед .
Вот полный код примера:
<html> <head> <title>onbeforeunload.html</title> <script> window.onbeforeunload = function () { } function myfun() { alert("The page has been refreshed."); } </script> <body onload="myfun()"> Hello World!<br> </body> </html>
Попробуйте, уйдите с этой страницы, а затем вернитесь, используя кнопки «Назад» или «Вперед» в своем браузере.
Он отлично работает в IE, FF и Chrome.
Конечно, внутри функции myfun вы можете делать все, что захотите .
Дополнительная информация: http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript
источник
Вы можете использовать localStorage или sessionStorage ( http://www.w3schools.com/html/html5_webstorage.asp ) для установки флага (вместо использования скрытой формы).
источник
Использование этой страницы, особенно с учетом комментария @sajith об ответе @Nick White и этой страницы: http://www.mrc-productivity.com/techblog/?p=1235
<form name="ignore_me" style="display:none"> <input type="text" id="reloadValue" name="reloadValue" value="" /> </form> $(function () { var date = new Date(); var time = date.getTime(); if ($("#reloadValue").val().length === 0) { $("#reloadValue").val(time); } else { $("#reloadValue").val(""); window.location.reload(); } });
источник
Вот версия jQuery. Я столкнулся с необходимостью использовать его несколько раз из-за того, как Safari Desktop / Mobile обрабатывает кеш, когда пользователь нажимает кнопку возврата.
$(window).bind("pageshow", function(event) { if (event.originalEvent.persisted) { // Loading from cache } });
источник
Сегодня я столкнулся с аналогичной проблемой, и я решил ее с помощью localStorage (здесь с небольшим количеством jQuery):
$(function() { if ($('#page1').length) { // this code must only run on page 1 var checkSteps = function () { if (localStorage.getItem('steps') == 'step2') { // if we are here, we know that: // 1. the user is on page 1 // 2. he has been on page 2 // 3. this function is running, which means the user has submitted the form // 4. but steps == step2, which is impossible if the user has *just* submitted the form // therefore we know that he has come back, probably using the back button of his browser alert('oh hey, welcome back!'); } else { setTimeout(checkSteps, 100); } }; $('#form').on('submit', function (e) { e.preventDefault(); localStorage.setItem('steps', 'step1'); // if "step1", then we know the user has submitted the form checkOrderSteps(); // ... then do what you need to submit the form and load page 2 }); } if ($('#page2').length) { // this code must only run on page 2 localStorage.setItem('steps', 'step2'); } });
Si в основном:
На странице 1, когда пользователь отправляет форму, мы устанавливаем значение "steps" в localStorage, чтобы указать, какой шаг сделал пользователь. В то же время мы запускаем функцию с таймаутом, которая проверяет, было ли это значение изменено (например, 10 раз в секунду).
На странице 2 мы немедленно меняем указанное значение.
Таким образом, если пользователь использует кнопку «Назад», а браузер восстанавливает страницу 1 в том же состоянии, в котором она была, когда мы ее покинули, функция checkSteps все еще работает и может обнаружить, что значение в localStorage было изменено (и может предпринять соответствующие действия. ). Как только эта проверка выполнит свою задачу, нет необходимости продолжать ее выполнение, поэтому мы просто больше не используем setTimeout.
источник