在我的 AJAX 应用程序中拦截对后退按钮的调用

IT技术 javascript ajax cross-browser browser-history
2021-02-10 23:14:05

我有一个 AJAX 应用程序。用户单击一个按钮,页面的显示就会发生变化。他们单击后退按钮,希望回到原始状态,但他们却转到浏览器中的上一页。

如何拦截并重新分配后退按钮事件?我研究过像 RSH 这样的库(我无法开始工作......),我听说使用哈希标签在某种程度上有帮助,但我无法理解。

6个回答

啊,后退按钮。您可能会想象“返回”会触发一个 JavaScript 事件,您可以像这样简单地取消该事件:

document.onHistoryGo = function() { return false; }

没有。根本没有这样的事件。

如果您确实有一个Web 应用程序(而不是仅具有一些 ajaxy 功能的网站),那么接管后退按钮(如您所提到的,URL 上带有片段)是合理的。Gmail 就是这样做的。我说的是当您的 Web 应用程序全部集中在一个页面中时,所有内容都是独立的。

该技术很简单——每当用户执行修改内容的操作时,重定向到您已经访问的相同 URL,但使用不同的哈希片段。例如

window.location.hash = "#deleted_something";
...
window.location.hash = "#did_something_else";

如果您的 Web 应用程序的整体状态是可散列的,那么这是使用散列的好地方。假设您有一个电子邮件列表,也许您可​​以连接它们的所有 ID 和已读/未读状态,并使用 MD5 哈希值作为片段标识符。

这种重定向(仅哈希)不会尝试从服务器获取任何内容,但会在浏览器的历史记录列表中插入一个插槽。所以在上面的例子中,用户点击“返回”,他们现在在地址栏中显示#deleted_something他们再次回击,他们仍在您的页面上,但没有哈希值。然后再回来,他们实际上回到了他们来自的地方。

现在是困难的部分,让您的 JavaScript 检测用户何时回击(以便您可以恢复状态)。您所做的就是观察窗口位置并查看它何时发生变化。随着投票。(我知道,糟糕,轮询。嗯,现在没有比这更好的跨浏览器了)。但是,您将无法判断它们是前进还是后退,因此您必须对散列标识符发挥创意。(也许是一个与序列号连接的哈希......)

这是代码的要点。(这也是 jQuery History 插件的工作方式。)

var hash = window.location.hash;
setInterval(function(){
    if (window.location.hash != hash) {
        hash = window.location.hash;
        alert("User went back or forward to application state represented by " + hash);
    }
}, 100);

对一个古老(但很流行)的问题给出最新答案:

HTML5 引入了history.pushState()history.replaceState()方法,它们分别允许您添加和修改历史条目。这些方法与window.onpopstate事件一起工作

使用history.pushState()更改在XMLHttpRequest更改状态后创建对象的 HTTP 标头中使用的引用者引用者将是this创建XMLHttpRequest对象其窗口所在的文档的 URL

来源:从 Mozilla 开发者网络操纵浏览器历史记录

使用 jQuery 我做了一个简单的解决方案:

$(window).on('hashchange', function() {
    top.location = '#main';
    // Eventually alert the user describing what happened
});

到目前为止,仅在 Google Chrome 中进行了测试。

这解决了我的 Web 应用程序的问题,该应用程序也是高度基于 AJAX 的。

这可能有点hack'ish - 但我称之为优雅的hacking ;-) 每当您尝试向后导航时,它都会在 URI 中弹出一个哈希部分,从技术上讲,这就是它然后尝试向后导航的部分。

它拦截点击浏览器按钮和鼠标按钮。并且您无法通过每秒多次单击来强制向后执行,这是在基于 setTimeout 或 setInterval 的解决方案中会出现的问题。

我认为右键单击后退按钮并立即后退两步仍然有效吗?
2021-03-23 23:14:05

我非常感谢darkporter 的回答中给出的解释,但我认为可以通过使用hashchange ”事件来改进它正如darkporter 解释的那样,您要确保所有按钮都更改window.location.hash 值。

  • 一种方法是使用<button>元素,然后将事件附加到它们然后设置window.location.hash = "#!somehashstring";.
  • 另一种方法是只为您的按钮使用链接,例如<a href="#!somehashstring">Button 1</a>. 单击这些链接时,哈希值会自动更新。

我在井号后面有感叹号的原因是为了满足 Google 的“hashbang”范式(阅读更多相关信息),如果您想被搜索引擎索引,这很有用。您的哈希字符串通常是名称/值对#!color=blue&shape=triangle或列表之类的#!/blue/triangle- 无论对您的 Web 应用程序有意义。

然后你只需要添加这段代码,它会在哈希值改变触发(包括点击后退按钮时)。似乎不需要轮询循环。

window.addEventListener("hashchange", function(){
    console.log("Hash changed to", window.location.hash);
    // .... Do your thing here...
});

除了 Chrome 36 之外,我没有在任何其他浏览器中进行过测试,但根据 caniuse.com 的说法,这应该可以在 IE8+、FF21+、Chrome21+ 和除 Opera Mini 之外的大多数其他浏览器中使用。

只是一个更新 - 谷歌不再推荐“hashbang”方法,因为他们现在能够成功抓取webmasters.googleblog.com/2015/10/...
2021-04-09 23:14:05

禁用浏览器后退按钮非常容易,就像下面的 JQuery 代码:

// History API 
if( window.history && window.history.pushState ){

  history.pushState( "nohb", null, "" );
  $(window).on( "popstate", function(event){
    if( !event.originalEvent.state ){
      history.pushState( "nohb", null, "" );
      return;
    }
  });
}

您可以在dotnsf 和 here thecssninja 中看到它的工作和更多示例

谢谢 !

这有效。但用户可以通过右键单击后退按钮转到上一页。
2021-03-24 23:14:05
@VimalS 是的!这就对了!你必须配置!请阅读我发送的相关页面!历史 API 中还有更多…… 优点:普通用户知道“右键单击”?.. 只是我觉得跌倒了……请。调整这以满足您的需求!
2021-03-24 23:14:05
这应该是公认的答案。它就像一个魅力!
2021-04-01 23:14:05
这是此页面上唯一在 Chrome v52.0 中对我有用的代码段。谢谢。
2021-04-10 23:14:05