如何让Firefox在从不同域的页面返回时触发popstate事件



我有一个简单的网页,即:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>History hacks</title>
<script>
window.onpopstate = function (e) {
alert("location: " + document.location + ", state: " + JSON.stringify(e.state));
}
window.onload = function (e) {
alert('page loaded');
}
</script>
</head>
<body>
<p> <a href="http://www.yahoo.com">Yahoo</a> <a href="#part1">Part 1</a></p>
</body>
</html>

现在,Chrome和Firefox在如何触发popstate事件方面存在许多差异(当我开始测试IE时,一想到我要面对的是什么,我就不寒而栗),但这里给我带来问题的是,每当我点击这两个链接中的任何一个时,Chrome都会触发popstate事件,然后当我点击后退按钮时再次触发。Firefox将触发更改哈希部分的链接的事件(如果哈希链接相同,则仅为第一次),如果我单击雅虎链接,然后单击后退按钮,则根本不会触发该事件。

那么,有没有一种方法可以让我在Firefox中告诉用户,用户刚刚从不同域上的一个完全不同的网站点击并返回我的页面?在Firefox中是否还有其他活动可以用于此目的?(当我从yahoo.com返回时,加载事件也不会被触发。)

当使用后退(或前进)按钮进入初始页面加载时,要获得popstate事件,请使用类似的replaceState()

window.onload = function(e) {
history.replaceState(null, null, document.URL);
}

要忽略Chrome在加载页面时生成的初始popstate,您可以在调用pushState/replaceState时标记状态,例如

history.pushState({myTag: true}, null, url);

然后您的popstate处理程序只过滤myTag

window.onpopstate = function(e) { 
if (!e.state.myTag) return; // none of my business
// code to handle popstate 
}

您可以将这两者结合起来,形成一个微不足道的跨浏览器解决方案:

window.onpopstate = function(e) { 
if (!e.state.myTag) return; // none of my business
// code to handle popstate 
}
window.onload = function(e) {
history.replaceState({myTag: true}, null, document.URL);
}

@Boris Zbarsky详细介绍了bfcache。我还没有想过如何将其与我的方法相结合。我只是通过添加页面unload处理程序来禁用它

window.onunload = function(e) { }

如果您希望在返回时显示页面时得到通知,即使页面缓存在页面缓存中,您可能正在查找pageshow事件。

请注意,如果没有加载事件,这也意味着页面仍然具有与导航离开时完全相同的DOM和脚本执行环境。基本上,这就像用户切换选项卡一段时间,而不是导航。

既然如此,你还想在这种情况下举办一场活动吗?当用户切换回包含您的页面的选项卡时,您是否得到要查找的事件?

在卸载之前,我重新加载页面(以获得初始状态),然后设置新的href

window.onunload = function(e) {
location.reload();
location.href = **new_url** ;
}

我必须这么做,因为firefox保存我页面的最后状态并恢复它,而不是重新创建它

我也有同样的问题,必须深入研究规范,找出为什么当使用后退按钮从不同域上的页面返回时,popstate事件在任何浏览器中都不会触发。事实证明,在这种情况下,popstate不应该激发,因为文档的状态changed不为true,而popstate只应该在状态changed为true时激发。对于更改为设置为真实规格的状态,说明:

如果指定条目的文档具有最新条目,并且该条目不是指定条目,则让state changed为true;否则就让它是假的。

我的理解是,当我们从不同域中的页面返回到我们的页面时,我们的页面没有最新条目,因为文档已经更改,新文档还没有最新的条目。再次来自规范:

浏览上下文中的每个文档也可以有一个最新条目。这是浏览上下文的会话历史记录最近被遍历到的文档的条目。创建文档时,文档最初没有最新条目。

但是,仍然有一种方法可以查看用户是否已返回您的页面,方法是使用历史的pushState或replaceState方法在页面中的history.state中设置标志,并在页面加载时检查history.state中是否存在此标志。

有关WHATWG HTML规范中处理popstate事件的部分的更多信息:https://html.spec.whatwg.org/multipage/browsers.html#history-遍历

最新更新