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

我想用JavaScript看是否有历史记录,后退按钮在浏览器上是否可用。

226369 次浏览

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

<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个不同的页面:一个是兼容后退按钮的“好浏览器”页面,一个是告诉他们更新浏览器的“坏浏览器”页面

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

你不能直接检查后退按钮是否可用。你可以查看history.length>0,但如果当前页面中也有之前页,这也是成立的。当history.length===0.返回按钮不可用时,只能是确定

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

事实上,用历史做任何事情通常都是一个非常糟糕的主意。历史导航是chrome浏览器,不是网页。添加“返回”链接通常会引起更多用户的困惑,而不是它的价值。

简单的回答:你不能。

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

history.previous

然而,这是行不通的。的问题是,在大多数浏览器中,这被认为是一个安全违规,通常只返回未定义的

history.length

是其他人建议的属性 然而,,长度并不完全有效,因为它并不表示你所在历史中的在哪里。此外,它并不总是从相同的数字开始。例如,一个未设置有登录页的浏览器将从0开始,而另一个使用登录页的浏览器将从1开始。

alt text

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

history.back();

 history.go(-1);

如果你不能返回,那么点击链接就没有任何作用。

还有另一种检查方法——检查推荐人。第一页通常会有一个空的引用。

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

这似乎很管用:

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

我的代码让浏览器返回一个页面,如果失败,它加载一个回退url。它还可以检测标签的变化。

当后退按钮不可用时,回退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);
}

我是这样做的。

我使用“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到目前为止)。

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);
var fallbackUrl = "home.php";
if(history.back() === undefined)
window.location.href = fallbackUrl;

小心使用window.history.length,因为它还包括window.history.forward()的条目

所以你可能有window.history.length,它有多个条目,但是没有历史回溯条目。 这意味着如果你触发window.history.back()

,什么都不会发生

我在我的项目中使用了一个片段:

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来管理浏览器历史记录。


为什么要比较历史。2的长度?

因为Chrome的开始页面是浏览器历史记录中的第一项。


history.length和user行为的可能性很少:

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

我省略的情况下,当用户登陆当前页面后点击链接从外部网站没有target="_blank"

注2: document.referrer是空的,当你打开网站输入它的地址,也当网站使用ajax加载子页面,所以我停止检查这个值在第一种情况下。

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

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

它的工作原理是这样的:如果浏览器打开一个从未打开过的新url,历史。长度会变长。

你可以改变哈希值

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

要得到一个从未显示的url,然后历史。长度会得到真正的长度。

  var realHistoryLength = history.length - 1

但是,它并不总是工作得很好,我不知道为什么,特别是当url自动跳转很快。

还有另一个附近完美的解决方案,来自另一个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上工作。

解决方案

'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 ()解构的任务的文档。

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

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

限制

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

基于答案在这里在这里。我认为,更确切的答案是检查这是否是一个新标签中的新页面。

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

不同的是,对于链接的答案,我们不会检查referrer,因为新选项卡仍然会有一个引用。

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

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

在我的情况下,我想回到历史上一个返回按钮,但如果用户打开的第一页是我的应用程序的子页,它会回到主页。

解决方案是,一旦应用程序被加载,我只是做了一个替换历史状态:

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

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

window.history.length == 1

此功能适用于Chrome, Firefox和Edge。 如果你想在没有窗口历史记录的情况下隐藏或删除网页上的后退按钮,你可以使用下面这段JQuery代码,它在上述3种浏览器的最新版本上都有效

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

我使用了一点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>
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);
}

我在我的网站上的常见问题解答中使用了Angular中的window.history

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

我的“退出”逻辑策略是基于条目ID的,然后返回到那个状态的状态数。

所以进入:

  enterState: { navigationId:number } = {navigationId: 1}


constructor() {
this.enterState = window.history.state
}

假设用户正在浏览FAQ

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

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

正如你所看到的,当用户在faq中开始时,我也使用了一个回退,在这种情况下,state.navigationId1,我们想要路由回去,替换第一个状态并显示主页(为此我使用Angular路由器,但当你处理自己的路由时,你也可以使用history.replaceState)

供参考:

这工作为我使用react,但可以在另一种情况下工作;当历史记录在第一页时(你不能返回)window.history.state将为null,所以如果你想知道你是否可以返回,你只需要:

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

文档:

History.state属性返回一个表示状态的值 历史堆栈的顶端。这是一种看待国家的方式 而不需要等待popstate事件

这可能会有帮助:

const prev = window.location.pathname;
window.history.back();
setTimeout(() => {
if (prev === window.location.pathname) {
// Do something else ...
}
}, 1000);

我正在使用Angular,我需要检查是否有历史记录,触发location.back(),否则重定向到父路由。

来自https://stackoverflow.com/a/69572533/18856708的解决方案工作良好。

constructor(
private activatedRoute: ActivatedRoute,
private router: Router,
private location: Location,
}
...


back(): void {
if (window.history.state === null) {
this.router.navigate(['../'], { relativeTo: this.activatedRoute });
return;
}


this.location.back();
}

这是我的解决方案:

function historyBack() {
console.log('back');
window.history.back() || window.history.go(-1);
if (!window.history.length) window.close();
var currentUrl = window.location.href;
setTimeout(function(){
// if location was not changed in 100 ms, then there is no history back
if(current === window.location.href){
console.log('History back is empty!');
}
}, 100);
}
function historyForward() {
console.log('forward');
window.history.forward() || window.history.go(+1);
var current = window.location.href;
setTimeout(function(){
// if location was not changed in 100 ms, then there is no history forward
if(current === window.location.href){
console.log('History forward is empty!');
}
}, 100);
}

下面的解决方案将导航回来,并告诉是否发生了导航:

async function goBack() {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => reject('nowhere to go'), 100);
window.history.back();
const onBack = () => {
window.removeEventListener('beforeunload', onBack);
window.removeEventListener('popstate', onBack);
clearTimeout(timer);
resolve(true);
};
window.addEventListener('beforeunload', onBack);
window.addEventListener('popstate', onBack);
});
}


// usage
await goBack().catch(err => console.log('failed'));

工作原理:

  1. 试着导航回去
  2. 添加事件监听器,在导航到另一个网站或同一网站上的另一个页面时触发(SPA网站等)
  3. 如果上述事件在100毫秒内没有发生,就可以推断出没有地方可以回去

注意goBack()是一个异步函数。