检测浏览器中的返回按钮点击

76

我需要检测用户是否点击了返回按钮。

为此,我正在使用

window.onbeforeunload = function (e) {
}

如果用户点击返回按钮,它是有效的。但是,如果用户点击浏览器的 F5 或刷新按钮,则此事件也会被触发。我该如何解决?


你读过 https://dev59.com/zXRB5IYBdhLWcg3wQFLu 吗? - Pulkit Agarwal
你可以在这里找到答案。 - Sedat Polat
3
抱歉,我无法在重复的问题上添加答案...不过,可以通过以下方式完成(检测后退按钮):window.performance && window.performance.navigation.type == 2 - Master DJon
6个回答

67

就 AJAX 而言...

在使用大多数使用 AJAX 导航页面特定部分的 Web 应用程序时,按返回按钮是一个巨大的问题。我不认为“必须禁用按钮意味着你做错了什么”,实际上,不同领域的开发人员长期以来一直遇到这个问题。这是我的解决方案:

window.onload = function () {
    if (typeof history.pushState === "function") {
        history.pushState("jibberish", null, null);
        window.onpopstate = function () {
            history.pushState('newjibberish', null, null);
            // Handle the back (or forward) buttons here
            // Will NOT handle refresh, use onbeforeunload for this.
        };
    }
    else {
        var ignoreHashChange = true;
        window.onhashchange = function () {
            if (!ignoreHashChange) {
                ignoreHashChange = true;
                window.location.hash = Math.random();
                // Detect and redirect change here
                // Works in older Firefox and Internet Explorer 9
                // * it does mess with your hash symbol (anchor?) pound sign
                // delimiter on the end of the URL
            }
            else {
                ignoreHashChange = false;
            }
        };
    }
}

据我所知,这在Chrome和Firefox中都有效。

1
你说得完全正确。我查了一下,我可以让旧版本的FF和IE与这个模型一起工作。看看这个人的帖子:http://www.adequatelygood.com/2010/7/Saner-HTML5-History-Management - Gus Crawford
很好的解决方案,这在我目前正在开发的一个ajax应用程序中非常有效。谢谢。 - Jim22150
那么,如果您确认要返回浏览,现在该如何重定向? - AAlferez
1
  1. 如果您希望仅捕获事件但保留原始后退按钮行为,则应在window.onpopstate事件中添加history.go(-2);
  2. 我认为只有当URL包含“#”锚点时,window.onhashchange才会起作用。
- BornToCode
1
如果地址栏中没有哈希值(onhashchange事件不会触发),在IE9中此方法将无法正常工作。注册事件之前别忘了添加默认的哈希值。 - Wittaya
显示剩余7条评论

61

如果浏览器不支持 "onbeforeunload",请尝试以下方法:

jQuery(document).ready(function($) {

  if (window.history && window.history.pushState) {

    $(window).on('popstate', function() {
      var hashLocation = location.hash;
      var hashSplit = hashLocation.split("#!/");
      var hashName = hashSplit[1];

      if (hashName !== '') {
        var hash = window.location.hash;
        if (hash === '') {
          alert('Back button was pressed.');
        }
      }
    });

    window.history.pushState('forward', null, './#forward');
  }

});

函数 window.history.pushState 是对象 window.history 的一个子级/方法。仅测试该函数是否足够吗? - Oliver Schafeld
1
@OliverSchafeld 测试 window.history.pushState 只有(或首先)在浏览器实现历史记录 API 的情况下才能抛出 Cannot read property 'pushState' of undefined。因此,这两个测试是必需的,并且需要按照特定的顺序进行。 - Nico Prat
@Nico Prat:啊,当然,谢谢。像这样测试不存在的属性 !!window.history.madeupproperty 的结果是 false。所以我猜 if(!!window.history.pushState) 可能会起作用。但是我无法得到 IE9(http://caniuse.com/#feat=history) 进行适当的测试。但是简单地检查 !!window.notexistent.madeup 会抛出“无法读取属性...”的错误。因此,确实需要 if (window.history && window.history.pushState),而且顺序也很重要。 - Oliver Schafeld
在Chrome、FF和IE11中对我有效。 - Greg Trevellick
2
非常有用的代码,但正如@Portekoi指出的那样,不能阻止两次按下后退按钮。为了实现完全的阻止功能,在alert('...')行之后添加了最后一行window.history.pushState('forward', null, './#forward')。这就解决了问题......在后退按钮点击时没有刷新或任何明显的效果。 - Nowdeen

9
我知道的最好方法:
window.onbeforeunload = function (e) {
    var e = e || window.event;
    var msg = "Do you really want to leave this page?"

    // For Internet Explorer and Firefox
    if (e) {
        e.returnValue = msg;
    }

    // For Safari / Chrome
    return msg;
};

2
这在谷歌浏览器中不起作用。 - Riz
2
这并不会完全禁用返回按钮,而是阻止任何浏览(后退、前进、刷新),并允许用户通过一个超出您控制范围的提示来停止它。 - Gus Crawford
1
这将禁止离开页面,包括关闭页面、返回和前进,并且不回答问题。 - Danger

7
我是这样检测返回按钮的:
window.onload = function () {
if (typeof history.pushState === "function") 
{
    history.pushState("jibberish", null, null);
    window.onpopstate = function () 
    {
        history.pushState('newjibberish', null, null);
        // Handle the back (or forward) buttons here
        // Will NOT handle refresh, use onbeforeunload for this.
    };
}

它可以工作,但我必须在Chrome中创建一个cookie来检测我第一次进入页面,因为当我没有通过cookie进行控制进入页面时,浏览器会执行返回操作而不是点击任何返回按钮。

if (typeof history.pushState === "function") 
{
    history.pushState("jibberish", null, null); 
    window.onpopstate = function () {
        if (((x = usera.indexOf("Chrome")) != -1) && 
              readCookie('cookieChrome') == null) 
        {
            addCookie('cookieChrome', 1, 1440);      
        } 
        else 
        {
            history.pushState('newjibberish', null, null);  
        }
    };
}

非常重要的是history.pushState("jibberish", null, null); 会复制浏览器历史记录。

我该如何解决这个问题?


4

由于后退按钮是浏览器的功能,更改默认功能可能会很困难。不过,有一些解决方法。请查看本文:

Q311 如何禁用浏览器的“返回”按钮?

通常,需要禁用后退按钮是编程问题/缺陷的一个很好的指标。我建议寻找替代方法,例如设置会话变量或存储表单是否已提交的cookie。


15
如果您进行任何现代操作,后退按钮的默认操作是不适当的。这是因为后退按钮是在Ajax出现之前,解决Web不实用问题的一种权宜之计。 - Morg.

3

不,实际上我有一个表单,在提交表单后,我会将用户重定向到另一个页面。因此,在这里,我不希望用户点击返回按钮并返回到表单页面。 - facebook
3
@ibh: 或许Post/Redirect/Get (PRG)模式适合您的需求。 - Marcel Korpel
3
如果你允许他们进入页面,但在点击按钮后设置一个变量(或会话或cookie),告诉应用程序不再显示表单,这样岂不更容易?你可以简单地隐藏表单,并提供另一个“感谢您已填写表单”的页面,或者如果该变量已设置,则自动重定向。这将防止他们以原来的方式导航。 - bpeterson76
@ibh:或者使用Ajax发送表单(带有正常的非JavaScript备选项),这样您就可以在成功后让表单消失,而不会向浏览器历史记录添加新页面。 - Marcel Korpel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接