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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/829046/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 10:46:50  来源:igfitidea点击:

How do I detect if a user has got to a page using the back button?

ajaxbrowserback-button

提问by Tom

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!

这个问题类似于Track when user hit back button on the browser,但不一样......我有一个解决方案,并在这里发布以供参考和反馈。如果有人有更好的选择,我会全力以赴!

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.

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

The issue is that if:

问题是,如果:

  1. the page is loaded without the description
  2. a description is added by the user
  3. the page is navigated away from by clicking a link
  4. the user clicks the back button
  1. 页面加载时没有描述
  2. 用户添加了描述
  3. 通过单击链接将页面导航离开
  4. 用户点击后退按钮

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?

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

回答by Nick White

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

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

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

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

回答by Bassem

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.

当前所有主要浏览器都支持 window.performance。

回答by Drew Baker

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

回答by Nes

You can solve it using the onbeforeunloadevent:

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

window.onbeforeunload = function () { }

Having an onbeforeunloadempty 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 myfunfunction.

当然,你可以在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

回答by Tom

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.htmlare not important, so the following should suffice:

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

stale.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?

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

回答by rerezz

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) 来设置标志(而不是使用隐藏表单)。

回答by nmit026

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();
    }
});

回答by getup8

For modern browsers, this seems to be the right way now:

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

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

This is still "Experimental" as of Jan 2020, but seems to be supported well.

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

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

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

回答by Wes

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

回答by s427

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”来指示用户已采取的步骤。同时,我们启动一个带有超时的函数来检查这个值是否已经改变(例如 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.

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