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


当前回答

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

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

其他回答

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

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

你可以改变哈希值

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

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

  var realHistoryLength = history.length - 1

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

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

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

工作原理:

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

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

解决方案

'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。请参阅有关窗口的文档。获取更多信息的位置。

接下来,调用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...');
  }
}

限制

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

我用的是window。在我的网站上的常见问题解答。

当用户想退出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,在这种情况下,状态。navigationId为1,我们想要路由回去,替换第一个状态,并显示主页(为此我使用Angular路由器,但你也可以使用历史记录。当你处理自己的路由时,也可以使用replaceState)

供参考:

history.go history.state history.replaceState Angular.router.navigateByUrl

这是我的解决方案:

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