Chrome在没有用户交互的情况下,如果没有用户交互,则不会触发后退按钮的popstate事件。

48

我正在尝试使用"pushState"和"popstate"事件来捕获后退按钮导航,然而,在Firefox中,popstate事件能够正确触发,但在Chrome中(版本76.0.3809.87(官方构建)(64位))如果没有用户交互,则不能触发

经过测试,似乎只有当用户与页面交互时(即点击文档上的某个地方)才会触发popstate事件。因此,如果您加载页面而没有进行交互并单击后退按钮,则不会调用popstate功能。

我添加了一个Fiddle来展示这一点:https://jsfiddle.net/0xwvLndu/

要在Chrome中测试Fiddle,只需单击链接并单击后退按钮。你将看不到警报。然后再次单击链接,但这次请单击Fiddle文档中的任何位置,然后单击后退按钮,警报将被触发。

我在Chromium论坛上找到了一些讨论,可能与这种怪异现象有关,也许是为了防止历史条目被滥用而实施的 - https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/OCS7g72HtyIhttps://github.com/WICG/interventions/issues/21#issuecomment-425609246

如果是这样的话,是否意味着不能再依赖popstate来捕获后退按钮动作,如果是这样,是否有解决方法?

以下是我一直在测试的示例:

window.addEventListener('load', function() {
    history.pushState(null, null, document.URL);
});

window.addEventListener('popstate', function(event) {
    alert('test');
});

我期望警报被触发时无论用户是否交互都会返回上一页,但在Chrome中这并没有发生。


我最近一直在处理popstate以还原滚动位置,所以这方面还很新鲜,但我仍然不理解这个问题。也许如果你有逐步说明(或图表),就可以得到更多反馈。 - Drenai
@Drenai 感谢您的反馈。我已经编辑了我的问题,试图使其更具体地针对手头的问题。希望这样能更清晰明了。 - Praemon
11
我在下面的链接中阅读了更多相关信息。看起来Chrome正有意地防止劫持默认返回按钮的行为(而且是出于良好的原因)。如果你找到一个绕过这个限制的方法,我怀疑它将不会是可靠的,因为未来的Chrome版本可能会再次修补它。https://nakedsecurity.sophos.com/2019/05/09/chrome-plans-to-save-you-from-sites-that-mess-with-your-back-button/ - Drenai
@Drenai 感谢您的文章 - 帮助确认了这个变化。我确实看到了它的原因,尽管这意味着合法的用例不再起作用。我想我需要寻找其他方法来实现我所需的功能(但可能会牺牲用户体验)。 - Praemon
2
我很高兴遇到这个问题。我真的不明白为什么当我点击“返回”时页面会重新加载,但是一旦我在点击“返回”之前在页面上点击了一些地方,一切都按预期工作了。这太奇怪了。 - Alex Peters
2个回答

3

正如其他评论中所建议的,这应该是浏览器软件的设计意图,以防止劫持其默认的返回按钮行为。


3

尝试添加一个 setTimeout 为0的延迟操作

window.onpopstate = () => setTimeout(alert.bind(window, "Pop"), 0);

在编写处理popstate事件的函数时,需要考虑到类似window.location这样的属性已经反映了状态更改(如果它影响当前URL),但document可能仍然没有。 如果目标是捕获新文档状态已完全就绪的时刻,则应使用零延迟setTimeout()方法调用来有效地将其内部回调函数放置在浏览器事件循环的末尾:window.onpopstate =()=> setTimeout(doSomeThing,0);

内容摘自 https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event

顺便提一句,建议不要使用此方法,因为浏览器随时可能删除它。


2
截至撰写本评论时,似乎即使在Chrome中也不能可靠地工作。 - Austin R. Scott

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接