Ajax 如何检测用户是否已使用“后退”按钮进入页面?

Ajax 如何检测用户是否已使用“后退”按钮进入页面?,ajax,browser,back-button,Ajax,Browser,Back Button,这个问题类似于,但不同于。。。我有一个解决方案,并张贴在这里作为参考和反馈。如果有谁有更好的选择,我洗耳恭听 情况是,我有一个带有“就地编辑”的页面,一个la flickr。也就是说,有一个“单击此处添加说明”DIV,单击该DIV时,它会变成一个带有保存和取消按钮的文本区域。单击“保存”将数据发布到服务器以更新数据库,并将新的描述放在DIV中,而不是文本区域。如果页面被刷新,新的描述将从数据库中显示,并带有“单击编辑”选项。如今,Web2.0已经相当标准了 问题在于,如果: 加载该页时没有说明

这个问题类似于,但不同于。。。我有一个解决方案,并张贴在这里作为参考和反馈。如果有谁有更好的选择,我洗耳恭听

情况是,我有一个带有“就地编辑”的页面,一个la flickr。也就是说,有一个“单击此处添加说明”DIV,单击该DIV时,它会变成一个带有保存和取消按钮的文本区域。单击“保存”将数据发布到服务器以更新数据库,并将新的描述放在DIV中,而不是文本区域。如果页面被刷新,新的描述将从数据库中显示,并带有“单击编辑”选项。如今,Web2.0已经相当标准了

问题在于,如果:

  • 加载该页时没有说明
  • 说明由用户添加
  • 通过单击链接,页面将被导航到其他位置
  • 用户单击后退按钮
  • 然后(从浏览器的缓存中)显示的是页面的版本,其中没有包含新描述的动态修改的DIV

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


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

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

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

    <!-- 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>
    
    客户端代码更新页面时,需要按如下方式标记修改:

    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\u stale\u页面
    函数,该函数将在必要时刷新页面。第一次加载时(即修改后,
    reload\u stale\u页面
    功能将不起任何作用。)

    
    window.parent.reload_stale_page();
    

    从我在这个阶段的(最低限度的)测试来看,这似乎按预期工作。我忽略了什么吗?

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


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

    本文对此进行了解释。请参阅下面的代码:

    
    显示的功能页面(evt){
    如果(evt.persisted){
    警报(“调用了pageshow事件处理程序。页面刚从页面缓存中恢复(例如,从“后退”按钮)。”;
    }否则{
    警报(“为初始加载调用了pageshow事件处理程序。这与加载事件相同。”);
    }
    }
    函数页隐藏(evt){
    如果(evt.persisted){
    警报(“调用了pagehide事件处理程序。页面已挂起并放入页面缓存。”);
    }否则{
    警报(“页面隐藏事件处理程序调用页面销毁。这与卸载事件相同。”);
    }
    }
    window.addEventListener(“pageshow”,pageshow,false);
    addEventListener(“pagehide”,pageHidden,false);
    
    您可以使用onbeforeunload事件解决此问题:


    window.onbeforeunload=function(){}
    使用此页面,特别是结合@sajith对@Nick White答案的评论和此页面:

    
    $(函数()
    {
    变量日期=新日期();
    var time=date.getTime();
    if($(“#重载值”).val().length==0)
    {
    $(“#重新加载值”).val(时间);
    }
    其他的
    {
    $(“#重载值”).val(“”);
    window.location.reload();
    }
    });
    
    您可以使用localStorage或sessionStorage()设置标志(而不是使用隐藏形式)。

    我今天遇到了类似的问题,我使用localStorage解决了这个问题(这里使用了一点jQuery):

    基本上:

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

    在第2页,我们立即更改所述值


    因此,如果用户使用“后退”按钮,浏览器将第1页还原为我们离开时的状态,则checkSteps函数仍在运行,并且能够检测到localStorage中的值已更改(并可以采取适当的操作)。一旦该检查完成了它的目的,就不需要继续运行它,因此我们不再使用setTimeout。

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

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

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

    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。

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

    const perfEntries=performance.getEntriesByType('navigation');
    if(perfEntries.length&&perfEntries[0]。类型==='back\u forward'){
    log('用户从后退或前进按钮到达这里');
    }
    
    截至2020年1月,这仍然是“实验性的”,但似乎得到了很好的支持


    在其他人的评论中发现了这一点(感谢姆拉登)——在Chrome 88中似乎工作得很好

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

    这与你所引用的问题有什么不同?问题是相似的,但我认为环境和答案是不同的,我可能错了
    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>
        <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>
    
    <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();
        }
    });
    
    $(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');
        }
    
    });
    
    $(window).bind("pageshow", function(event) {
        if (event.originalEvent.persisted) {
            // Loading from cache
        }
    });
    
    if (window.performance && window.performance.navigation.type === window.performance.navigation.TYPE_BACK_FORWARD) {
        alert('Got here using the browser "Back" or "Forward" button.');
    }
    
    if(String(window.performance.getEntriesByType("navigation")[0].type) === "back_forward"){
    // Actions here, such as refresh page, etc.
    }