我有一个 AJAX 应用程序。用户单击一个按钮,页面的显示就会发生变化。他们单击后退按钮,希望回到原始状态,但他们却转到浏览器中的上一页。
如何拦截并重新分配后退按钮事件?我研究过像 RSH 这样的库(我无法开始工作......),我听说使用哈希标签在某种程度上有帮助,但我无法理解。
我有一个 AJAX 应用程序。用户单击一个按钮,页面的显示就会发生变化。他们单击后退按钮,希望回到原始状态,但他们却转到浏览器中的上一页。
如何拦截并重新分配后退按钮事件?我研究过像 RSH 这样的库(我无法开始工作......),我听说使用哈希标签在某种程度上有帮助,但我无法理解。
啊,后退按钮。您可能会想象“返回”会触发一个 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 的解决方案中会出现的问题。
我非常感谢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 之外的大多数其他浏览器中使用。
禁用浏览器后退按钮非常容易,就像下面的 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 中看到它的工作和更多示例
谢谢 !