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


Answers:


119

简短的回答:不能。

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

history.previous

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

history.length

是一个属性,其他人已经建议......
但是,长度不完全,因为它并不表示工作地方在历史上你。此外,它并不总是以相同的数字开头。例如,未设置为具有登录页面的浏览器从0开始,而另一个使用登录页面的浏览器从1开始。

替代文字

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

history.back();

要么

 history.go(-1);

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


这是很好的信息,但是不能解决问题。详细说明一些可在任何浏览器上正常工作的代码。也许是一个代码,该代码首先检查您使用的浏览器。
圣地亚哥·本达维德

5
我的意思是,没有明确的答案。您是在说每种方法的利弊,而不是说如何获得一个脚本来检查您使用的浏览器并有条件地执行一个或其他代码段。
圣地亚哥·本达维德

我想知道您的意思是“这个问题是,在大多数浏览器中,这被认为是违反安全性的行为”。另一个线程中的另一个用户还指出,能够获取客户端的浏览器历史记录是在违反安全性,但是并没有解释这是为什么。谁能举例说明安全威胁是什么?
凯文·钱德拉

网站不应该知道可能包含间接个人信息的用户历史。网站可以使用跟踪/ Cookie来了解用户在网站本身上所做的事情,但是例如,不应允许他们弄清楚我使用的银行,孩子上的学校等等。因此,浏览器将不允许访问该属性
McAden

84

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

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

2
出于隐私原因,可以隐藏引荐来源网址。
Kornel

11
当不是通过链接加载页面而是通过在地址栏中输入URL或加载书签时,引荐来源网址始终为空。但是,当浏览器选项卡/窗口之前已加载另一个页面时,此类页面肯定具有历史记录!
ygoe 2012年

1
但跨多页的网站导航应用的解决方案

36
如果使用target =“ _ blank”打开一个窗口以强制打开新窗口,则该窗口不起作用。浏览器上的“后退”按钮不起作用,但是会有一个document.referrer
Mike_K 2013年

3
如果您是从安全(HTTPS)页面转到不安全页面(HTTP),则此方法将不起作用,因为这将删除引荐来源网址。
凯文·博德斯

54

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

当后退按钮不可用时,后备网址将在500毫秒后加载,因此浏览器有足够的时间加载前一页。立即加载后备网址window.history.go(-1);会导致浏览器使用后备网址,因为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);
}

6
我认为这确实是问题的核心,一个人为什么要关心,以及如何以可靠的方式和前后一致的方式实际对此做些什么。
克里斯·马里西克

1
这一直有效,直到我获取了后退按钮所在的网址并将其粘贴到chrome中的新标签中。单击后退按钮导致发送到一个空选项卡。:(
karlingen

2
这是Chrome的默认行为。您“访问”了该页面chrome://newtab,因此可以返回历史记录。
redelschaap

请谨慎处理,因为网络连接速度慢,您会很定期地访问后备网址。
卡梅克

14

这是我的方法。

我用'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)。


1
到目前为止,这是对该问题的最佳答案。您可以轻松地替换为window.location.href = fallbackwindow.close()并且也可以使用。
维塔尼'17

13

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

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不会更改。.因此,它不能正常工作
Ciprian Mocanu

不幸的是,您是对的。我仅将此代码段与“一步一步”结构一起使用…
gregmatys,

12

这似乎可以解决问题:

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将不允许脚本关闭窗口。


3
我发现这并不工作,除非我使用的setTimeout与几百毫秒左右的尝试运行下一个语句之前的延迟,否则它会运行history.back()后,如果想运行
肯·费林

我没有亲身经历过,那是哪个浏览器?
xtrahelp.com 2014年

我在下面的答案中使用setTimeout函数工作得很好。例如:setTimeout(function(){window.close()},400);
gilchris 2014年

2
window.close()被许多现代浏览器视为安全风险。有些只是不允许您这样做。
鲁迪·克肖

您可以在window.history.back()之后执行任何操作;window.close(); 只是一个例子
hariszaman

9

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

如果这还不够好,那么您几乎可以做的就是打电话,history.back()并且如果此后仍然加载页面,则后退按钮不可用!当然,如果手段后退按钮可用的,你刚刚从页面导航离开。您不允许取消中的导航onunload,因此,要停止实际上发生的后退,您要做的所有事情就是从中返回某些内容onbeforeunload,这将导致出现一个令人讨厌的大提示。这不值得。

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


2
关于长度-并非所有浏览器都如此。某些浏览器会将当前页面视为历史记录项,并从1开始。您必须包括浏览器检测。
麦克阿登

其实我以为是永远10我觉得这是个难题,我认为浏览器总是会做出1更多响应。事实证明,Opera和IE认为不是这样-很好。
bobince 2010年

1
“历史记录导航适用于浏览器chrome,而不适用于网页”-同意
Brian

9

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

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


5

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

这样为我工作:函数goBackOrTo(targetUrl){var currentUrl = window.location.href; window.history.go(-1); setTimeout(function(){//如果在800毫秒内未更改位置,则没有历史记录if(currentUrl === window.location.href){//重定向到站点根window.location.href = targetUrl; }},800); }
alfonx 2015年

2

我想出了以下方法。它利用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")


1
我最喜欢这个,我只是更改windows.onbeforeunload为事件侦听器,window.addEventListener("beforeunload", function (event) { useFallback = false; });所以它不会覆盖window.onbeforeunload。
MiChAeLoKGB

2

这里这里的答案的基础上。我认为,更结论性的答案只是检查这是否是新标签中的新页面。

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

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

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

1
谢谢。你救了我的日子:)。
比耶(Bijay Yadav)

1

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

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上对我有用。


0

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

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

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

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

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

  var realHistoryLength = history.length - 1

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


0

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

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

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

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

这样,我只需要检查history.state.root后再返回。如果为true,则改为替换历史记录:

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

我认为没有其他好的用例。如果您想查看应用程序外部的历史记录,可能不是一个好主意。
Maxwell sc


-2

'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分配的文档。

现在,如果用户尝试在打开时返回https://domain/,我们将不会触发if语句,因此也不会触发该window.history.back()方法,因此用户将留在我们的网站中。该URL等于,[]其长度为0,并且0 > 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,则此解决方案将不起作用。使用此解决方案之前,请查看文档以了解更多信息。


-5

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

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

编辑:

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


2
history.back是一个功能。您想检查一下是否history.length > 0可以返回history.back()
pixl coder

3
同样[],在NodeList上也没有意义,并且您不能将字符串分配给事件处理程序。
bobince 2010年

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.