Как определить, попал ли пользователь на страницу с помощью кнопки «Назад»? - PullRequest
85 голосов
/ 06 мая 2009

Этот вопрос похож на Отслеживание, когда пользователь нажимает кнопку "Назад" в браузере , но не то же самое ... У меня есть решение, и я публикую его здесь для справки и обратной связи. Если у кого-то есть варианты получше, я весь в ушах!

Ситуация такова, что у меня есть страница с "редактированием на месте", а-ля flickr. То есть есть DIV «нажмите здесь, чтобы добавить описание», который при нажатии превращается в TEXTAREA с кнопками «Сохранить» и «Отмена». Нажатие кнопки «Сохранить» отправляет данные на сервер для обновления базы данных и помещает новое описание в DIV вместо TEXTAREA. Если страница обновлена, новое описание отображается из базы данных с опцией «нажмите, чтобы изменить». В наши дни довольно стандартный материал для Web 2.0.

Проблема в том, что если:

  1. страница загружается без описания
  2. описание добавлено пользователем
  3. переход на страницу осуществляется по ссылке
  4. пользователь нажимает кнопку возврата

Затем отображается (из кэша браузера) версия страницы без динамически измененного DIV, содержащего новое описание.

Это довольно большая проблема, поскольку пользователь предполагает, что его обновление было потеряно, и не обязательно поймет, что ему нужно обновить страницу, чтобы увидеть изменения.

Итак, вопрос таков: как можно пометить страницу как измененную после ее загрузки, а затем определить, когда пользователь «возвращается к ней», и принудительно обновить ее в этой ситуации?

Ответы [ 9 ]

76 голосов
/ 13 апреля 2011

Используйте скрытую форму. Данные формы сохраняются (как правило) в браузерах, когда вы перезагружаете или нажимаете кнопку «Назад», чтобы вернуться на страницу. Следующее идет на вашей странице (вероятно, в нижней части):

<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 inline вверху страницы (js second), если задержка пользователя является серьезной проблемой. *

40 голосов
/ 24 августа 2017

Вот очень простое современное решение этой старой проблемы.

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 в настоящее время поддерживается всеми основными браузерами.

13 голосов
/ 16 июня 2011

Эта статья объясняет это. Смотрите код ниже: 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>
2 голосов
/ 02 июня 2016

Вы можете использовать localStorage или sessionStorage (http://www.w3schools.com/html/html5_webstorage.asp) для установки флага (вместо использования скрытой формы).

2 голосов
/ 04 июня 2015

Вы можете решить эту проблему, используя событие 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

2 голосов
/ 06 мая 2009

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

Первый этап решения - добавить на страницу следующее:

<!-- 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>

Из моего (минимального) тестирования на данном этапе это, кажется, работает как хотелось бы. Я что-то упустил из виду?

1 голос
/ 31 марта 2017

Вот версия jQuery. Я сталкивался с необходимостью использовать его несколько раз из-за того, что настольный / мобильный Safari обрабатывает кэш, когда пользователь нажимает кнопку возврата.

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        // Loading from cache
    }
});
1 голос
/ 26 февраля 2016

Использование этой страницы, особенно с учетом комментария @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();
    }
});
0 голосов
/ 08 июня 2016

Сегодня я столкнулся с подобной проблемой и решил ее с помощью 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.

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