关于javascript:如何检查用户是否可以返回浏览器历史记录

How to check if the user can go back in browser history or not

我想使用JavaScript来查看是否存在历史记录,这意味着浏览器上是否提供了后退按钮。


简短的回答:不能。

从技术上讲,有一种准确的方法可以检查属性:

1
history.previous

但是,它不起作用。问题在于,在大多数浏览器中,这被认为是违反安全性的,通常只会返回未定义的结果。

1
history.length

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

alt text

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

1
history.back();

要么

1
 history.go(-1);

只是预期如果您无法返回,则单击链接不会执行任何操作。


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

1
2
3
4
5
if (document.referrer =="") {
    window.close()
} else {
    history.back()
}


我的代码允许浏览器返回上一页,如果失败,它将加载后备URL。它还可以检测标签变化。

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

1
2
3
4
5
6
7
8
9
10
11
12
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);
}


这似乎可以解决问题:

1
2
3
4
5
6
7
8
9
10
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将不允许脚本关闭窗口。


这是我的方法。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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)。


您无法直接检查后退按钮是否可用。您可以查看history.length>0,但是如果当前页面之前也有页面,则将适用。您只能确定history.length===0时后退按钮不可用。

如果这还不够好,那么您几乎可以做的就是调用history.back(),并且如果此后仍加载页面,则后退按钮不可用!当然,这意味着如果后退按钮可用,那么您就已经离开了该页面。您不允许取消onunload中的导航,因此,要阻止实际发生的后退,您要做的所有事情就是从onbeforeunload返回某些内容,这将导致出现一个大的烦人提示。这不值得。

实际上,对历史做任何事情通常是一个非常糟糕的主意。历史记录导航适用于浏览器chrome,而不适用于网页。添加"返回"链接通常会引起更多的用户混乱,其价值不菲。


我在项目中使用了一个代码段:

1
2
3
4
5
6
7
8
9
10
11
12
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加载子页面时,因此在第一种情况下,我不再检查此值。


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

因此,您的window.history.length可能包含多个条目,但没有历史记录后退条目。
这意味着如果您触发window.history.back(),则什么也不会发生


history.length是无用的,因为它不会显示用户是否可以返回历史记录。
同样,不同的浏览器使用初始值0或1-取决于浏览器。

可行的解决方案是使用$(window).on('beforeunload'事件,但是我不确定如果通过ajax加载页面并使用pushState更改窗口历史记录,它将无法正常工作。

因此,我使用了下一个解决方案:

1
2
3
4
5
6
7
8
9
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);


在这里和这里的答案的基础上。我认为,更确定的答案只是检查这是否是新标签中的新页面。

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

不同地,对于链接的答案,我们不检查referrer,因为新选项卡仍将具有引荐来源网址。

1
2
3
4
5
6
if( (1 < history.length) {
    history.back();
}
else {
    window.close();
}


我想出了以下方法。它利用onbeforeunload事件来检测浏览器是否开始离开页面。如果不在特定时间范围内,它将重定向到备用。

1
2
3
4
5
6
7
8
9
10
11
12
13
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")调用此函数。


还有另一个接近完美的解决方案,取自另一个SO答案:

1
2
3
4
5
6
7
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上似乎对我有用。


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

它的工作原理是:如果浏览器打开了一个从未打开过的新URL,则history.length将增加。

所以你可以像这样更改哈希

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

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

1
  var realHistoryLength = history.length - 1

但是,它并不总是能很好地工作,而且我也不知道为什么,尤其是当url自动跳转时。


1
2
3
4
5
6
'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"]的东西。可以这样写:

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

有关更多信息,请参见有关Array.prototype.filter()和Destructuring分配的文档。

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

1
2
3
4
5
6
7
8
'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,则此解决方案将不起作用。使用此解决方案之前,请查看文档以了解更多信息。


1
2
3
var fallbackUrl ="home.php";
if(history.back() === undefined)
    window.location.href = fallbackUrl;


我不确定这是否可行,并且尚未经过完全测试,但是请尝试以下操作:

1
2
3
4
5
6
7
8
9
10
11
<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();
    }

在HTML中:

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

编辑:

您还可以做的是研究哪些浏览器支持后退功能(我认为它们都支持),并使用在此页面上找到并进行了详细描述的标准JavaScript浏览器检测对象。然后,您可以有2个不同的页面:一个用于与"后退"按钮兼容的"优质浏览器"页面,另一个用于指示"不良浏览器"告诉他们更新其浏览器的页面


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