【问题标题】:How to check if the user can go back in browser history or not如何检查用户是否可以返回浏览器历史记录
【发布时间】:2011-04-05 00:53:34
【问题描述】:

我想使用 JavaScript 来查看是否有历史记录,我的意思是浏览器上的后退按钮是否可用。

【问题讨论】:

  • 如果您的目的是检查goback 是否正常工作,我认为您可以在回退调用之后设置一个计时器......因此如果goback 不起作用,您可以重定向到后备链接。

标签: javascript


【解决方案1】:

简短回答:你不能。

从技术上讲,有一种准确的方法,那就是检查属性:

history.previous

但是,它不起作用。问题在于,在大多数浏览器中,这被视为安全违规,通常只返回 undefined

history.length

是其他人建议的属性...
但是,长度不能完全起作用,因为它没有指示您在历史中的位置是。此外,它并不总是以相同的数字开头。例如,未设置登录页面的浏览器从 0 开始,而使用登录页面的另一个浏览器将从 1 开始。

大多数情况下,添加的链接会调用:

history.back();

 history.go(-1);

如果您无法返回,那么单击该链接将无济于事。

【讨论】:

  • 这是很好的信息,但它不能解决问题。它将详细说明一些实际适用于任何浏览器的代码。也许是首先检查您正在使用的浏览器的代码。
  • 我的意思是没有明确的答案。您是在说每种方法的优缺点,而不是如何获取一个脚本来检查您正在使用的浏览器并有条件地执行一个或其他代码。
  • 我想知道您所说的“问题是在大多数浏览器中这被认为是安全违规”是什么意思另一个线程中的另一个用户也指出能够获取客户端的浏览器历史记录是违规的安全,但没有解释为什么会这样。谁能举例说明安全威胁是什么?
  • 网站不应该知道可能包含间接个人信息的用户历史记录。网站可以使用跟踪/cookies 来了解用户在网站上所做的事情,但不应该让他们知道我使用的银行、我的孩子上哪所学校等等......因此,浏览器不允许访问该属性
【解决方案2】:

还有另一种检查方法 - 检查引荐来源网址。第一页通常会有一个空的referer...

if (document.referrer == "") {
    window.close()
} else {
    history.back()
}

【讨论】:

  • 出于隐私原因可以隐藏引荐来源网址。
  • 当页面不是通过链接加载而是通过在地址栏中输入 URL 或加载书签来加载时,引荐来源网址始终为空。但是,当浏览器选项卡/窗口之前加载过另一个页面时,这些页面肯定有历史记录!
  • 但适用于跨多页网站导航的解决方案
  • 如果使用 target="_blank" 打开窗口以强制打开新窗口,则此操作无效。浏览器上的后退按钮不起作用,但是会有一个document.referrer
  • 如果您从安全 (HTTPS) 页面转到不安全页面 (HTTP),这将不起作用,因为这会剥离引荐来源网址。
【解决方案3】:

我的代码让浏览器返回一页,如果失败,它会加载一个后备网址。它还检测主题标签的变化。

当后退按钮不可用时,后备 url 将在 500 毫秒后加载,因此浏览器有足够的时间加载上一页。在window.history.go(-1); 之后加载后备url 会导致浏览器使用后备url,因为js 脚本还没有停止。

function historyBackWFallback(fallbackUrl) {
    fallbackUrl = fallbackUrl || '/';
    var prevPage = window.location.href;

    window.history.go(-1);

    setTimeout(function(){ 
        if (window.location.href == prevPage) {
            window.location.href = fallbackUrl; 
        }
    }, 500);
}

【讨论】:

  • 我认为这确实抓住了问题的核心,即为什么一个人关心这个问题,以及可以以可靠且一致的方式实际做些什么。
  • 这一直有效,直到我获取后退按钮所在的网址并将其粘贴到 chrome 的新选项卡中。单击后退按钮会导致被发送到一个空选项卡。 :(
  • 这是 Chrome 的默认行为。您“访问”了页面chrome://newtab,因此您可以回到历史。
  • 小心这一点,因为网络连接速度较慢,您会经常点击后备网址。
【解决方案4】:

这就是我的做法。

我使用 'beforeunload' 事件 来设置布尔值。然后我设置了一个超时来观察'beforeunload'是否触发。

var $window = $(window),
    $trigger = $('.select_your_link'),
    fallback = 'your_fallback_url';
    hasHistory = false;

$window.on('beforeunload', function(){
    hasHistory = true;
});

$trigger.on('click', function(){

    window.history.go(-1);

    setTimeout(function(){
        if (!hasHistory){
            window.location.href = fallback;
        }
    }, 200);

    return false;
});

似乎可以在主流浏览器中使用(目前已测试 FF、Chrome、IE11)。

【讨论】:

  • 这是迄今为止该问题的最佳答案。您可以轻松地将window.location.href = fallback 替换为window.close(),它也可以。
【解决方案5】:

我在项目中使用了一个 sn-p:

function back(url) {
    if (history.length > 2) {
        // if history is not empty, go back:
        window.History.back();
    } else if (url) {
        // go to specified fallback url:
        window.History.replaceState(null, null, url);
    } else {
        // go home:
        window.History.replaceState(null, null, '/');
    }
}

仅供参考:我使用History.js 来管理浏览器历史记录。


为什么要将 history.length 与数字 2 进行比较?

因为 Chrome 的起始页被计为浏览器历史记录中的第一项。


history.length 和用户行为的可能性很小:

  • 用户在浏览器中打开新的空标签,然后运行一个页面。 history.length = 2 并且在这种情况下我们要禁用 back(),因为用户将转到空白选项卡。
  • 用户通过点击之前某处的链接在新标签中打开页面。 history.length = 1 再次我们要禁用 back() 方法。
  • 最后,用户在重新加载几个页面后到达当前页面。 history.length > 2 现在可以启用back()

注意:我省略了当用户在没有target="_blank"的情况下点击外部网站链接后进入当前页面的情况。

注意 2:document.referrer 在您通过输入其地址打开网站以及网站使用 ajax 加载子页面时为空,因此我在第一种情况下停止检查此值。

【讨论】:

  • 这种方法对我很有效。我实际上为我在后备中使用的页面存储了静态后备链接。
  • 但是,如果你回去,history.length 不会改变.. 所以,它不能正常工作
  • 很遗憾,您说得对。我只使用这个带有“单步后退”结构的 sn-p……
【解决方案6】:

这似乎可以解决问题:

function goBackOrClose() {  

    window.history.back();
    window.close(); 

    //or if you are not interested in closing the window, do something else here
    //e.g. 
    theBrowserCantGoBack();

}

调用 history.back() 然后 window.close()。如果浏览器能够返回历史记录,它将无法进入下一条语句。如果无法返回,它将关闭窗口。

但是,请注意,如果通过输入 url 到达该页面,则 firefox 不会允许脚本关闭窗口。

【讨论】:

  • 我发现这不起作用,除非我在尝试运行下一条语句之前使用延迟几百毫秒左右的 setTimeout,否则它会在运行历史记录后运行。返回()
  • 我没有亲身体验过,是哪个浏览器?
  • 我在下面的答案中使用 setTimeout 函数工作得很好。例如:setTimeout(function() { window.close() }, 400);
  • window.close() 被许多现代浏览器视为安全风险。有些人就是不让你这样做。
  • 你可以在 window.history.back(); 之后做任何事情窗口.close();只是一个例子
【解决方案7】:

注意window.history.length,因为它还包含window.history.forward() 的条目

因此,您可能有超过 1 个条目的 window.history.length,但没有历史回溯条目。 这意味着如果你开火window.history.back()

【讨论】:

    【解决方案8】:

    您不能直接检查后退按钮是否可用。您可以查看history.length>0,但如果当前页面也有ahead 页面,那将是正确的。只有当history.length===0 时,您才能确定后退按钮不可用。

    如果这还不够好,您所能做的就是致电history.back(),如果之后您的页面仍在加载,则返回按钮不可用!当然,这意味着如果后退按钮 可用,则您刚刚离开该页面。你不能取消onunload 中的导航,所以你能做的就是阻止后面实际发生的所有事情就是从onbeforeunload 返回一些东西,这将导致出现一个大的烦人的提示。不值得。

    事实上,对历史做任何事情通常都是一个非常糟糕的主意。历史导航适用于浏览器 chrome,而不是网页。添加“返回”链接通常会导致用户混淆而不是其价值。

    【讨论】:

    • 关于长度 - 甚至在所有浏览器中都不是。某些浏览器将当前页面计为历史记录项并从 1 开始。您必须包括浏览器检测。
    • 其实我一直以为是10 是个脑残,我认为浏览器总是会回复 1 或更多。事实证明 Opera 和 IE 的想法不同——很好。
    • “历史导航适用于浏览器 chrome,而不是网页” - 同意
    【解决方案9】:

    history.length 没有用,因为它没有显示用户是否可以回到历史。 不同的浏览器也使用初始值 0 或 1 - 这取决于浏览器。

    有效的解决方案是使用$(window).on('beforeunload' 事件,但我不确定如果页面是通过 ajax 加载并使用 pushState 更改窗口历史记录,它是否会起作用。

    所以我使用了下一个解决方案:

    var currentUrl = window.location.href;
    window.history.back();
    setTimeout(function(){
        // if location was not changed in 100 ms, then there is no history back
        if(currentUrl === window.location.href){
            // redirect to site root
            window.location.href = '/';
        }
    }, 100);
    

    【讨论】:

    • 这样对我有用:function goBackOrTo(targetUrl){ var currentUrl = window.location.href; window.history.go(-1); setTimeout(function(){ // 如果位置在 800 毫秒内没有更改,则没有历史记录返回 if(currentUrl === window.location.href){ // 重定向到站点根 window.location.href = targetUrl; } }, 800); }
    【解决方案10】:

    基于答案herehere。我认为,更确凿的答案只是检查这是否是新标签中的新页面。

    如果页面的历史不止一个,那么我们可以回到当前页面之前的页面。如果不是,则该选项卡是新打开的选项卡,我们需要创建一个新选项卡。

    不同的是,对于链接的答案,我们不会检查 referrer,因为新标签仍然会有推荐人。

    if(1 < history.length) {
        history.back();
    }
    else {
        window.close();
    }
    

    【讨论】:

      【解决方案11】:

      我想出了以下方法。它利用 onbeforeunload 事件来检测浏览器是否开始离开页面。如果它不在某个时间跨度内,它只会重定向到后备。

      var goBack = function goBack(fallback){
          var useFallback = true;
      
          window.addEventListener("beforeunload", function(){
            useFallback = false;
          });
      
          window.history.back();
      
          setTimeout(function(){
              if (useFallback){ window.location.href = fallback; }
          }, 100); 
      }
      

      您可以使用goBack("fallback.example.org") 调用此函数。

      【讨论】:

      • 我最喜欢这个,我只是将windows.onbeforeunload 更改为事件监听器window.addEventListener("beforeunload", function (event) { useFallback = false; });,所以它不会覆盖window.onbeforeunload。
      【解决方案12】:

      还有一个接近完美的解决方案,取自another SO answer

      if( (1 < history.length) && document.referrer ) {
          history.back();
      }
      else {
          // If you can't go back in history, you could perhaps close the window ?
          window.close();
      }
      

      有人报告说使用 target="_blank" 时它不起作用,但它似乎在 Chrome 上对我有用。

      【讨论】:

        【解决方案13】:

        这对我使用 react 有效,但可以在另一种情况下工作;当历史记录在第一页时(您无法返回),window.history.status 将为空,因此如果您想知道是否可以返回,您只需要:

         if (window.history.state == null) {
            //you cannot go back
         }
        

        【讨论】:

          【解决方案14】:

          浏览器有后退和前进按钮。我想出了这个问题的解决方案。但它会影响浏览器的转发操作并导致某些浏览器出现错误。

          它的工作原理是这样的:如果浏览器打开一个从未打开过的新 url,history.length 将会增长。

          这样你就可以改变散列

            location.href = '#__transfer__' + new Date().getTime() 
          

          要获得一个从未显示的 url,那么 history.length 将获得真实的长度。

            var realHistoryLength = history.length - 1
          

          但是,它并不总是很好,我不知道为什么,尤其是当 url 自动快速跳转时。

          【讨论】:

            【解决方案15】:

            我试图找到一个解决方案,这是我能得到的最好的解决方案(但效果很好,甚至是我在这里找到的最简单的解决方案)。

            就我而言,我想用后退按钮返回历史记录,但如果用户打开的第一个页面是我的应用程序的子页面,它将返回到主页面。

            解决方案是,一旦加载应用程序,我就对历史状态进行了替换:

            history.replaceState( {root: true}, '', window.location.pathname + window.location.hash)
            

            这样,我只需要在返回之前检查history.state.root。如果为真,我会替换历史记录:

            if(history.state && history.state.root)
                history.replaceState( {root: true}, '', '/')
            else
                history.back() 
            

            【讨论】:

            • 我认为没有其他好的用例。如果您想在应用之外查看历史记录,这可能不是一个好主意。
            【解决方案16】:
            var func = function(){ console.log("do something"); };
            if(document.referrer.includes(window.location.hostname) && history.length-1 <= 1){
                func();
            }
            else{
                const currentUrl = window.location.href;
                history.back();
                setTimeout(function(){
                    currentUrl === window.location.href && func();
                }, 100);
            }
            

            【讨论】:

              【解决方案17】:

              我在 Angular 中使用 window.history 来解决我网站上的常见问题。

              当用户想要退出FAQ时,他们可以点击退出按钮(在返回按钮旁边)

              我对这个“退出”策略的逻辑是基于入口 ID,然后返回到该状态的状态数。

              所以输入:

                enterState: { navigationId:number } = {navigationId: 1}
              
                constructor() {
                  this.enterState = window.history.state
                }
              

              假装用户浏览了常见问题解答

              然后,当用户单击退出按钮时,读取当前状态并计算您的增量:

              exitFaq() {
                  // when user started in faq, go back to first state, replace it with home and navigate
                  if (this.enterState.navigationId === 1) {
                    window.history.go((window.history.state.navigationId - 1) * -1)
                    this.router.navigateByUrl('/')
                    //  non-angular
                    //  const obj = {Title: 'Home', Url: '/'}
                    //  window.history.replaceState(obj, obj.Title, obj.Url)
                  } else {
                    window.history.go(this.enterState.navigationId - window.history.state.navigationId - 1)
                  }
                }
              

              如您所见,我还使用了用户在常见问题解答中启动时的回退,在这种情况下,state.navigationId1,我们想要返回,替换第一个状态并显示主页(对于我使用的是 Angular 路由器,但您也可以在处理自己的路由时使用 history.replaceState

              供参考:

              【讨论】:

                【解决方案18】:

                我找到了一个真正有效的 JQuery 解决方案

                window.history.length == 1

                这适用于 Chrome、Firefox 和 Edge。 如果您想在没有窗口历史记录的情况下隐藏或删除已开发网页上的后退按钮,您可以在上述所有 3 个浏览器的最新版本上使用以下对我有用的 JQuery 代码。

                $(window).load(function() {
                        if (window.history.length == 1) {
                            $("#back-button").remove();
                        }
                    })
                

                【讨论】:

                  【解决方案19】:
                  var fallbackUrl = "home.php";
                  if(history.back() === undefined)
                      window.location.href = fallbackUrl;
                  

                  【讨论】:

                  • 这看起来超级简单?!是否在各种浏览器上进行了测试?
                  • 在 Chrome 中 history.back()undefined 仅在空白标签页上
                  【解决方案20】:

                  我正在使用一点 PHP 来实现结果。不过有点生锈了。但它应该可以工作。

                  <?php 
                  function pref(){ 
                    return (isset($_SERVER['HTTP_REFERER'])) ? true : '';
                  }
                  ?>
                  <html>
                  <body>
                  
                  <input type="hidden" id="_pref" value="<?=pref()?>">
                  
                  <button type="button" id="myButton">GoBack</button>
                  
                  <!-- Include jquery library -->
                  <script> 
                    if (!$('#_pref').val()) { 
                      $('#myButton').hide() // or $('#myButton').remove()
                    } 
                  </script>
                  </body>
                  </html>
                  

                  【讨论】:

                    【解决方案21】:

                    解决方案

                    'use strict';
                    function previousPage() {
                      if (window.location.pathname.split('/').filter(({ length }) => length > 0).length > 0) {
                        window.history.back();
                      }
                    }
                    

                    说明

                    window.location.pathname 会给你当前的 URI。例如https://domain/question/1234/i-have-a-problem 将给出/question/1234/i-have-a-problem。有关详细信息,请参阅有关 window.location 的文档。

                    接下来,对split() 的调用将为我们提供该URI 的所有片段。因此,如果我们采用之前的 URI,我们将得到类似 ["", "question", "1234", "i-have-a-problem"] 的内容。有关详细信息,请参阅有关 String.prototype.split() 的文档。

                    这里调用filter()是为了过滤掉反斜杠生成的空字符串。它基本上只会返回长度大于 1(非空字符串)的片段 URI。所以我们会有类似["question", "1234", "i-have-a-question"] 的东西。可以这样写:

                    'use strict';
                    window.location.pathname.split('/').filter(function(fragment) {
                      return fragment.length > 0;
                    });
                    

                    有关更多信息,请参阅有关 Array.prototype.filter()Destructuring assignment 的文档。

                    现在,如果用户在https://domain/ 上尝试返回,我们不会触发 if 语句,因此不会触发window.history.back() 方法,因此用户将留在我们的网站中。此 URL 将等效于长度为 0[],而 0 &gt; 0 为 false。因此,默默地失败了。当然,您可以根据需要记录一些内容或执行其他操作。

                    'use strict';
                    function previousPage() {
                      if (window.location.pathname.split('/').filter(({ length }) => length > 0).length > 0) {
                        window.history.back();
                      } else {
                        alert('You cannot go back any further...');
                      }
                    }
                    

                    限制

                    当然,如果浏览器不支持History API,此解决方案将不起作用。在使用此解决方案之前,请查看文档以了解更多信息。

                    【讨论】:

                      【解决方案22】:

                      我不确定这是否有效并且它完全未经测试,但试试这个:

                      <script type="text/javascript">
                      
                          function goBack() {
                              history.back();
                          }
                      
                          if (history.length > 0) { //if there is a history...
                              document.getElementsByTagName('button')[].onclick="goBack()"; //assign function "goBack()" to all buttons onClick
                          } else {
                              die();
                          }
                      </script>
                      

                      在 HTML 中的某处:

                      <button value="Button1"> //These buttons have no action
                      <button value="Button2">
                      

                      编辑:

                      您还可以做的是研究哪些浏览器支持返回功能(我认为它们都支持)并使用在this page 上找到并详细描述的标准 JavaScript 浏览器检测对象。然后你可以有 2 个不同的页面:一个用于与后退按钮兼容的“好浏览器”,一个用于“坏浏览器”,告诉他们去更新他们的浏览器

                      【讨论】:

                      • history.back 是一个函数。你想检查history.length &gt; 0 是否返回history.back()
                      • NodeList 上的 [] 也没有任何意义,您不能将字符串分配给事件处理程序。
                      【解决方案23】:

                      检查window.history.length是否等于0。

                      【讨论】:

                      • 不是一个好方法,因为 history.length 并没有告诉你你在历史中的位置......
                      • @Ron Reiter:是的,我认为这个问题的最佳答案和其他 cmets 在一年前就已经确定了......
                      猜你喜欢
                      • 2017-11-04
                      • 1970-01-01
                      • 2015-05-18
                      • 1970-01-01
                      • 2015-06-14
                      • 2021-12-02
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多