history.pushState不会触发'popstate'事件。

29

为什么

window.addEventListener('popstate', () => alert('pop'));

window.history.pushState(null, '', '/foo');

为什么我的 pushState 没有触发 popstate 事件?

NB: 在最新的 Chrome 浏览器上测试

--

根据 MDN 的说法:

每次活动历史记录条目更改时,都会向窗口发送 popstate 事件。如果要激活的历史记录条目是通过调用 pushState 或受 replaceState 调用影响而创建的,则 popstate 事件的 state 属性包含历史记录条目状态对象的副本。

6个回答

65

每次调用history.pushState()时,您可以手动触发window上的popstate事件。

history.pushState(state, '', url);

var popStateEvent = new PopStateEvent('popstate', { state: state });
dispatchEvent(popStateEvent);

非常好的答案,非常感谢!! - Sachin
感谢 @sgtpep!这成功地触发了 addEventListener('popstate', event) - Binyamin

16

你提到的这一段话有些含糊不清。阅读同一页上的示例,很明显popstate只会在用户点击后退按钮时才会触发,而不是在脚本调用 pushState() 时触发。


12
当用户点击前进按钮时,popstate事件也会被触发。 - circuitry
pushstate确实会触发popstate事件!因此,“每当活动历史记录条目更改时,popstate事件都会分派到窗口”! - Alex Gill
1
@AlexGill 你有一个可以演示这种行为的测试用例吗?类似于:window.onpopstate = function(e) { alert('popstate'); } history.pushState(null, ''); - Sean Hogan
1
popstate事件也会在window.location.hash = "<some new hash>"时被触发。Dmitri Farkov在下面的回答中提到了这个细节,我认为这很重要。 - Goodword

14

您正在阅读的是MDN的“指南页”,它不是规范性内容。

考虑阅读MDN的“文档页面”关于WindowEventHandlers.onpopstate

请注意,仅调用history.pushState()或history.replaceState()不会触发popstate事件。只有通过浏览器操作才会触发popstate事件,比如点击后退按钮(或在JavaScript中调用history.back())。并且只有当用户在同一文档的两个历史记录条目之间导航时,才会触发该事件。

另一个未记录的触发popstate的方法是直接操作window.location对象。

// this also triggers popstate 
window.location.hash = "#some-new-hash"

这应该是被接受的答案,因为它涉及到window.location.hash的事情。 - Goodword
这种方式不会传递任何状态,它只适用于无状态操作。 - Amin
另一个关于事件如何工作的好解释可以在这里找到:https://www.codeguage.com/courses/js/events-popstate-event - robstarbuck

2

我的解决方案:

var url = "http://awesome.website.net/route/to/paradise";
window.history.pushState({}, "", url);
window.history.pushState({}, "", url); // yes twice
window.history.back();

它将通过“popstate”事件触发软导航,而无需进行HTTP请求。

这也是所有前端框架都做的吗? - elliottregan
1
这很糟糕,因为你最终会得到冗余的前向状态。不,框架不会这样做。它们只是有良好的代码,在popstatepushState之后调用相同的回调函数。 - Robo Robok

0

https://developer.mozilla.org/zh-CN/docs/Web/Events/popstate文档中提到:

请注意,仅调用history.pushState()history.replaceState()不会触发popstate事件。要触发popstate事件,需要进行浏览器操作,如单击“后退”或“前进”按钮(或在JavaScript中调用history.back()history.forward())。


-1

我也遇到了这个问题... 我认为只有在数据对象的顶层有与先前状态不同的内容时,事件才会触发。

尝试这样做:

var data = {rand: Math.random()};
window.history.pushState(data, '', '/foo');

这也不会调用popstate。至少在Firefox 26上不会。 - circuitry

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