如何使用后退按钮检测用户是否已到达页面?

时间:2023-01-27 16:00:49

This question is similar to Track when user hits back button on the browser, but not the same... I have a solution and am posting it here for reference and feedback. If anyone has any better options, I'm all ears!

这个问题类似于跟踪用户何时在浏览器上点击后退按钮,但不是相同的……我有一个解决方案,并在这里发布以供参考和反馈。如果有人有更好的选择,我洗耳恭听!

The situation is that I have a page with an "in place edit", a la flickr. I.e. there is a "click here to add a description" DIV, which when clicked turns into a TEXTAREA with Save and Cancel buttons. Clicking Save posts the data to the server to update the database and puts the new description in the DIV in place of the TEXTAREA. If the page is refreshed, the new description is displayed from the database with a "click to edit" option. Fairly standard web 2.0 stuff these days.

现在的情况是,我有一个页面,上面有一个“in place edit”,一个la flickr。例如,有一个“点击这里添加描述”DIV,当点击时,它会变成一个带有保存和取消按钮的文本区域。单击Save将数据发布到服务器以更新数据库,并将新的描述放在DIV中,取代TEXTAREA。如果刷新了页面,将从数据库中显示新的描述,并提供“单击以编辑”选项。这些天相当标准的web 2.0。

The issue is that if:

问题是如果:

  1. the page is loaded without the description
  2. 页面加载时没有描述。
  3. a description is added by the user
  4. 用户添加描述
  5. the page is navigated away from by clicking a link
  6. 通过单击链接可以将页面导航到其他位置
  7. the user clicks the back button
  8. 用户单击后退按钮

Then what is displayed (from the browser's cache) is the version of the page without the dynamically modified DIV containing the new description.

然后显示的(来自浏览器的缓存)是页面的版本,没有包含新描述的动态修改DIV。

This is a fairly big problem as the user assumes that their update has been lost and won't necessarily understand that they need to refresh the page to see the changes.

这是一个相当大的问题,因为用户假定他们的更新已经丢失,并且不一定理解他们需要刷新页面以查看更改。

So, the question is: How can you flag a page as being modified after it has loaded, and then detect when the user "goes back to it" and force a refresh in that situation?

因此,问题是:您如何标记一个页面在加载后被修改,然后在用户“返回到它”时检测它,并在这种情况下强制刷新?

9 个解决方案

#1


73  

Use a hidden form. Form data is preserved (typically) in browsers when you reload or hit the back button to return to a page. The following goes in your page (probably near the bottom):

使用一个隐藏的形式。当重新加载或单击back按钮返回页面时,(通常)在浏览器中保存表单数据。下面是你的页面(可能在底部):

<form name="ignore_me">
    <input type="hidden" id="page_is_dirty" name="page_is_dirty" value="0" />
</form>

In your javascript, you will need the following:

在您的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';
}

The js that sniffs the form has to execute after the html is fully parsed, but you could put both the form and the js inline at the top of the page (js second) if user latency is a serious concern.

当html被完全解析后,该表单的js就必须执行,但是如果用户延迟是一个严重的问题,那么可以将表单和js放在页面的顶部(js秒)。

#2


23  

Here is a very easy modern solution to this old problem.

对于这个老问题,有一个很简单的现代解决办法。

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 is currently supported by all major browsers.

窗口。所有主要浏览器都支持性能。

#3


11  

This article explains it. See the code below: http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/

本文解释了它。请参见下面的代码:http://www.webkit.org/blog/516/webkit-page-cache- style -cache- ionload -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>

#4


2  

As mentioned above, I had found a solution and am posting it here for reference and feedback.

如上所述,我找到了一个解决方案,并将其张贴在这里以供参考和反馈。

The first stage of the solution is to add the following to the page:

解决方案的第一阶段是将以下内容添加到页面:

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

The contents of fresh.html are not important, so the following should suffice:

新鲜的内容。html并不重要,所以以下内容就足够了:

<!-- fresh.html -->
<HTML><BODY></BODY></HTML>

When client side code updates the page, it needs to flag the modification as follows:

当客户端代码更新页面时,需要标记修改如下:

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 does all the work: When it is loaded it will call the reload_stale_page function which will refresh the page if necessary. The first time it is loaded (i.e. after the modification is made, the reload_stale_page function won't do anything.)

不新鲜的。html完成所有工作:当它被加载时,它将调用reload_stale_page函数,如果需要,它将刷新页面。第一次加载时(即修改完成后,reload_stale_page函数不会做任何事情)。

<!-- stale.html -->
<HTML><BODY>
<SCRIPT type="text/javascript">window.parent.reload_stale_page();</SCRIPT>
</BODY></HTML>

From my (minimal) testing at this stage, this seems to work as desired. Have I overlooked anything?

从我在这个阶段(最小)的测试来看,这似乎是理想的。我忽略了什么吗?

#5


2  

You can use localStorage or sessionStorage (http://www.w3schools.com/html/html5_webstorage.asp) to set a flag (instead of using a hidden form).

您可以使用localStorage或sessionStorage (http://www.w3schools.com/html/html5_webstorage.asp)设置标志(而不是使用隐藏的表单)。

#6


2  

Here's a jQuery version. I've run into needing to use it a few times due to the way Safari desktop/mobile handles the cache when a user presses the back button.

这是一个jQuery版本。由于用户按下后退按钮时Safari桌面/移动设备处理缓存的方式,我不得不多次使用它。

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        // Loading from cache
    }
});

#7


1  

You can solve it using the onbeforeunload event:

您可以使用onbeforeunload事件解决它:

window.onbeforeunload = function () { }

Having an onbeforeunload empty event manager function means the page will be re-built every single time it is accessed. Javascripts will re-run, server-side scripts will be re-run, the page will be built as if the user was hitting it for the very first time, even if the user got to the page just by hitting the back or forward button.

拥有onbeforeunload空事件管理器函数意味着每次访问页面时都会重新构建页面。javascript将重新运行,服务器端脚本将重新运行,页面将被构建,就像用户第一次点击它一样,即使用户通过点击后退或前进按钮到达页面。

Here is the full code of an example:

下面是一个示例的完整代码:

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

Try it, navigate away this page and then get back using "Back" or "Forward" buttons in your browser.

尝试一下,浏览这个页面,然后在浏览器中使用“后退”或“前进”按钮返回。

It works fine in IE, FF and Chrome.

它在IE、FF和Chrome上运行良好。

Of course you can do whatever you want inside myfun function.

当然你可以在myfun函数中做任何你想做的事。

More info: http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript

更多信息:http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript。

#8


1  

Using this page, especially incorporating the comment by @sajith about the answer by @Nick White and this page: http://www.mrc-productivity.com/techblog/?p=1235

使用这个页面,特别是包含@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();
    }
});

#9


0  

I've run into a similar problem today and I solved it with localStorage (here with a bit of jQuery):

今天我遇到了一个类似的问题,我用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 basically:

基本上如果:

On page 1, when the user submits the form, we set a value "steps" in localStorage to indicate what step the user has taken. At the same time, we launch a function with timeout that will check if this value has been changed (e.g. 10 times/second).

在第1页,当用户提交表单时,我们在localStorage中设置一个值“steps”,以指示用户所采取的步骤。同时,我们启动一个具有timeout的函数,该函数将检查这个值是否已经更改(例如,10次/秒)。

On page 2, we immediately change said value.

在第2页,我们立即改变了这个值。

So if the user uses the back button and the browser restores page 1 in the exact state it was when we left it, the checkSteps function is still running, and able to detect that the value in localStorage has been changed (and can take appropriate action). Once this check has filled its purpose, there's no need to continue running it, so we simply don't use setTimeout anymore.

因此,如果用户使用了back按钮,而浏览器在正确的状态中重新存储了第1页,那么当我们离开时,checkSteps函数仍在运行,并且能够检测到localStorage中的值已经更改(并可以采取适当的操作)。一旦这个检查完成了它的目的,就没有必要继续运行它了,所以我们不再使用setTimeout了。

#1


73  

Use a hidden form. Form data is preserved (typically) in browsers when you reload or hit the back button to return to a page. The following goes in your page (probably near the bottom):

使用一个隐藏的形式。当重新加载或单击back按钮返回页面时,(通常)在浏览器中保存表单数据。下面是你的页面(可能在底部):

<form name="ignore_me">
    <input type="hidden" id="page_is_dirty" name="page_is_dirty" value="0" />
</form>

In your javascript, you will need the following:

在您的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';
}

The js that sniffs the form has to execute after the html is fully parsed, but you could put both the form and the js inline at the top of the page (js second) if user latency is a serious concern.

当html被完全解析后,该表单的js就必须执行,但是如果用户延迟是一个严重的问题,那么可以将表单和js放在页面的顶部(js秒)。

#2


23  

Here is a very easy modern solution to this old problem.

对于这个老问题,有一个很简单的现代解决办法。

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 is currently supported by all major browsers.

窗口。所有主要浏览器都支持性能。

#3


11  

This article explains it. See the code below: http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/

本文解释了它。请参见下面的代码:http://www.webkit.org/blog/516/webkit-page-cache- style -cache- ionload -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>

#4


2  

As mentioned above, I had found a solution and am posting it here for reference and feedback.

如上所述,我找到了一个解决方案,并将其张贴在这里以供参考和反馈。

The first stage of the solution is to add the following to the page:

解决方案的第一阶段是将以下内容添加到页面:

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

The contents of fresh.html are not important, so the following should suffice:

新鲜的内容。html并不重要,所以以下内容就足够了:

<!-- fresh.html -->
<HTML><BODY></BODY></HTML>

When client side code updates the page, it needs to flag the modification as follows:

当客户端代码更新页面时,需要标记修改如下:

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 does all the work: When it is loaded it will call the reload_stale_page function which will refresh the page if necessary. The first time it is loaded (i.e. after the modification is made, the reload_stale_page function won't do anything.)

不新鲜的。html完成所有工作:当它被加载时,它将调用reload_stale_page函数,如果需要,它将刷新页面。第一次加载时(即修改完成后,reload_stale_page函数不会做任何事情)。

<!-- stale.html -->
<HTML><BODY>
<SCRIPT type="text/javascript">window.parent.reload_stale_page();</SCRIPT>
</BODY></HTML>

From my (minimal) testing at this stage, this seems to work as desired. Have I overlooked anything?

从我在这个阶段(最小)的测试来看,这似乎是理想的。我忽略了什么吗?

#5


2  

You can use localStorage or sessionStorage (http://www.w3schools.com/html/html5_webstorage.asp) to set a flag (instead of using a hidden form).

您可以使用localStorage或sessionStorage (http://www.w3schools.com/html/html5_webstorage.asp)设置标志(而不是使用隐藏的表单)。

#6


2  

Here's a jQuery version. I've run into needing to use it a few times due to the way Safari desktop/mobile handles the cache when a user presses the back button.

这是一个jQuery版本。由于用户按下后退按钮时Safari桌面/移动设备处理缓存的方式,我不得不多次使用它。

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        // Loading from cache
    }
});

#7


1  

You can solve it using the onbeforeunload event:

您可以使用onbeforeunload事件解决它:

window.onbeforeunload = function () { }

Having an onbeforeunload empty event manager function means the page will be re-built every single time it is accessed. Javascripts will re-run, server-side scripts will be re-run, the page will be built as if the user was hitting it for the very first time, even if the user got to the page just by hitting the back or forward button.

拥有onbeforeunload空事件管理器函数意味着每次访问页面时都会重新构建页面。javascript将重新运行,服务器端脚本将重新运行,页面将被构建,就像用户第一次点击它一样,即使用户通过点击后退或前进按钮到达页面。

Here is the full code of an example:

下面是一个示例的完整代码:

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

Try it, navigate away this page and then get back using "Back" or "Forward" buttons in your browser.

尝试一下,浏览这个页面,然后在浏览器中使用“后退”或“前进”按钮返回。

It works fine in IE, FF and Chrome.

它在IE、FF和Chrome上运行良好。

Of course you can do whatever you want inside myfun function.

当然你可以在myfun函数中做任何你想做的事。

More info: http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript

更多信息:http://www.hunlock.com/blogs/Mastering_The_Back_Button_With_Javascript。

#8


1  

Using this page, especially incorporating the comment by @sajith about the answer by @Nick White and this page: http://www.mrc-productivity.com/techblog/?p=1235

使用这个页面,特别是包含@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();
    }
});

#9


0  

I've run into a similar problem today and I solved it with localStorage (here with a bit of jQuery):

今天我遇到了一个类似的问题,我用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 basically:

基本上如果:

On page 1, when the user submits the form, we set a value "steps" in localStorage to indicate what step the user has taken. At the same time, we launch a function with timeout that will check if this value has been changed (e.g. 10 times/second).

在第1页,当用户提交表单时,我们在localStorage中设置一个值“steps”,以指示用户所采取的步骤。同时,我们启动一个具有timeout的函数,该函数将检查这个值是否已经更改(例如,10次/秒)。

On page 2, we immediately change said value.

在第2页,我们立即改变了这个值。

So if the user uses the back button and the browser restores page 1 in the exact state it was when we left it, the checkSteps function is still running, and able to detect that the value in localStorage has been changed (and can take appropriate action). Once this check has filled its purpose, there's no need to continue running it, so we simply don't use setTimeout anymore.

因此,如果用户使用了back按钮,而浏览器在正确的状态中重新存储了第1页,那么当我们离开时,checkSteps函数仍在运行,并且能够检测到localStorage中的值已经更改(并可以采取适当的操作)。一旦这个检查完成了它的目的,就没有必要继续运行它了,所以我们不再使用setTimeout了。