最终答案:
我对下面的第二次尝试回答非常满意。
但我真的不喜欢:
history.back();
history.forward();
我采用它来手动触发popstate 事件。
在实践中,我发现这种 hack 有时会奏效,有时会很慢,有时会完全失败。
在纸面上,感觉太临时了。
经过反复搜索和试验(这非常难找到),我终于找到了手动触发 popstate 事件的正确语法。
就像dispatching这个简单一样:
new Event('popstate')
像这样:
let myEvent = new Event('popstate');
window.dispatchEvent(myEvent);
所以最后的代码是:
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
let queryStringChange = new Event('popstate');
window.dispatchEvent(queryStringChange);
我能想到的最佳答案(第二次尝试):
基于以下内容:
我确定查询字符串将只需要检查:
-
页面加载或重新加载时;
-
当window.history.pushstate 被调用时;
-
或者当(正如 @Kaiido 在下面的 cmets 中敏锐地指出)通过前进和后退按钮访问页面时
我也知道:
-
window.load 事件侦听器涵盖第 1 点;
-
window.popstate 事件侦听器涵盖第 3 点。;
只剩下第 2 点。
处理第 2 点
正如 MDN 报告的那样:
请注意,只需调用 history.pushState() 或 history.replaceState()
不会触发 popstate 事件。 popstate 事件将被触发
通过执行浏览器操作,例如单击后退或前进
按钮(或在 JavaScript 中调用 history.back() 或 history.forward())。
来源: https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event
但这意味着,而不是使用(如下我第一次尝试):
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
checkQueryString(); // DIRECT INVOCATION OF FUNCTION
我可以改用:
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
history.back();
history.forward();
这意味着不需要直接调用该函数,我现在可以允许覆盖 第 3 点 的相同 window.popstate 事件侦听器完成其工作,从而为我提供更清晰、逻辑上更分离的代码。
注意我觉得……很奇怪……单独按下前进按钮会触发window.popstate事件监听器,但调用window.history.pushState()不会...(需要立即添加 history.back(); history.forward(); 以复制前进按钮的功能)。
但是,如上所述,这是我能想到的最好、最干净、最优化(就逻辑分离和未来代码维护而言)的解决方案。如果有人有更好的主意,我会很乐意转移绿勾。
第一次尝试回答:
我暂时得出结论,没有办法使用可以检测查询字符串何时更新的后台事件侦听器来实现此效果。
相反,因为我知道肯定查询字符串将只需要检查:
- 页面加载或重新加载时
-
window.history.pushstate 被调用时
我可以使用以下内容:
window.addEventListener('load', checkQueryString);
和
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
checkQueryString();