如何使用后退按钮检测用户是否已访问某个页面?

时间:2009-05-06 10:48:15

标签: ajax browser back-button

这个问题类似于Track when user hits back button on the browser,但不一样......我有一个解决方案,并将其发布在此处以供参考和反馈。如果有人有更好的选择,我全都听见了!

情况是我有一个带有“就地编辑”的页面,一个la flickr。即有一个“点击这里添加描述”DIV,点击后变成带有保存和取消按钮的TEXTAREA。单击“保存”将数据发布到服务器以更新数据库,并将新描述放在DIV中以代替TEXTAREA。如果刷新页面,则会使用“单击以编辑”选项从数据库中显示新描述。这些天相当标准的Web 2.0。

问题是如果:

  1. 页面加载时没有描述
  2. 用户添加了说明
  3. 点击链接
  4. 导航页面
  5. 用户点击后退按钮
  6. 然后显示的内容(来自浏览器的缓存)是没有动态修改的包含新描述的DIV的页面版本。

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

    所以,问题是:如何将页面标记为在加载后进行修改,然后检测用户何时“返回”并在该情况下强制刷新?

11 个答案:

答案 0 :(得分:76)

使用隐藏的表单。当您重新加载或点击后退按钮返回页面时,表单数据(通常)会保留在浏览器中。以下内容(可能在底部附近):

<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';
}

在完全解析html之后,必须执行嗅探表单的js,但如果用户延迟是一个严重问题,您可以将表单和js内联在页面顶部(js秒)。

答案 1 :(得分:40)

对于这个老问题,这是一个非常简单的现代解决方案。

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。

答案 2 :(得分:13)

本文解释了它。请参阅以下代码: 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>

答案 3 :(得分:4)

对于现代浏览器,这现在似乎是正确的方法:

const perfEntries = performance.getEntriesByType('navigation');
if (perfEntries.length && perfEntries[0].type === 'back_forward') {
  console.log('User got here from Back or Forward button.');
}

到2020年1月,这仍然是“实验性”,但似乎得到了很好的支持。

https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming

答案 4 :(得分:2)

如上所述,我找到了一个解决方案,并将其发布在此处以供参考和反馈。

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

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

从这个阶段的(最小)测试来看,这似乎可以正常工作。我忽略了什么吗?

答案 5 :(得分:2)

您可以使用 onbeforeunload 事件解决问题:

&#13;
&#13;
window.onbeforeunload = function () { }
&#13;
&#13;
&#13;

拥有 onbeforeunload 空事件管理器功能意味着每次访问页面时都会重新构建页面。 Javascripts将重新运行,服务器端脚本将重新运行,页面将被构建为好像用户第一次点击它,即使用户只需按下后退或前进按钮就可以访问该页面。

以下是示例的完整代码:

&#13;
&#13;
<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>
&#13;
&#13;
&#13;

尝试一下,离开此页面,然后使用&#34;返回&#34;或&#34;转发&#34;浏览器中的按钮。

它在IE,FF和Chrome中运行良好。

当然,你可以在 myfun 功能中做任何你想做的事。

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

答案 6 :(得分:2)

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

答案 7 :(得分:1)

使用此页面,特别是将@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();
    }
});

答案 8 :(得分:1)

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

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

答案 9 :(得分:0)

我今天遇到了类似的问题,我用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页,当用户提交表单时,我们在localStorage中设置一个值“steps”以指示用户采取了什么步骤。同时,我们启动一个超时功能,检查此值是否已更改(例如10次/秒)。

在第2页,我们立即更改了上述值。

因此,如果用户使用后退按钮并且浏览器以我们离开时的确切状态恢复第1页,则checkSteps功能仍在运行,并且能够检测到localStorage中的值已被更改(并且可以采取适当的行动)。一旦这个检查完成了它的目的,就没有必要继续运行它了,所以我们不再使用setTimeout了。

答案 10 :(得分:0)

在其他人的评论中发现了这一点(感谢 Mladen) - 似乎在 Chrome 88 中运行良好。

if(String(window.performance.getEntriesByType("navigation")[0].type) === "back_forward"){
// Actions here, such as refresh page, etc.
}