如何在 2019 年监听 window.location.search 的变化

Rou*_*ica 5 html javascript query-string pushstate popstate

我想在window.location.search 不重新加载文档的情况下进行更新,然后根据window.location.search.

当用户单击按钮时,该按钮的onclick事件会触发以下函数:

window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好。window.location.search浏览器 URL 栏中的更新。

但是我找不到检测此更新的通用后台事件侦听器-类似于onhashchange查询字符串。

我能想到的最好的是:

window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
window.history.back();

window.addEventListener('popstate', () => console.log(event.state.action));
Run Code Online (Sandbox Code Playgroud)

这有效,但我相信必须有更优雅的方法。

Rou*_*ica 5

最终答案:

我对下面的第二次尝试答案非常满意。

但我真的不喜欢:

history.back();
history.forward();
Run Code Online (Sandbox Code Playgroud)

我采用它来popstate手动触发事件。

在实践中,我发现这个黑客有时有效,有时很慢,有时甚至完全失败。

从纸面上看,感觉太临时了。

经过反复搜索和实验(这非常难以找到),我终于找到了手动触发事件的正确语法popstate

就这么简单dispatching

new Event('popstate')
Run Code Online (Sandbox Code Playgroud)

像这样:

let myEvent = new Event('popstate');
window.dispatchEvent(myEvent);
Run Code Online (Sandbox Code Playgroud)

所以最终的代码是:

window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
let queryStringChange = new Event('popstate');
window.dispatchEvent(queryStringChange);
Run Code Online (Sandbox Code Playgroud)

我能想到的最佳答案(第二次尝试):

建立在以下基础上:

我确信查询字符串只需要检查

  1. 当页面加载或重新加载时;

  2. 何时window.history.pushstate调用;

  3. 或者当(正如@Kaiido在下面的评论中敏锐指出的那样)通过前进和后退按钮访问页面时

我还知道:

  • 事件window.load监听器涵盖了第1点;
  • 事件window.popstate监听器涵盖了第3点;

只剩下第2点了。


处理第2点

MDN报道:

请注意,仅调用history.pushState()orhistory.replaceState() 不会触发 popstate 事件。popstate 事件将通过执行浏览器操作来触发 ,例如单击后退或前进按钮(或在 JavaScript 中调用history.back()or 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
Run Code Online (Sandbox Code Playgroud)

我可以用:

window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');
history.back();
history.forward();
Run Code Online (Sandbox Code Playgroud)

这意味着我现在可以允许覆盖第 3 点window.popstate的相同事件侦听器来完成其工作,而不需要直接调用该函数,从而为我提供更清晰、逻辑上更独立的代码。


注意,我发现它......很奇怪......单独按下前进按钮触发window.popstate事件侦听器,但调用window.history.pushState()不会......(需要立即添加history.back(); history.forward();以复制前进按钮的功能)。

但是,如上所述,这是我能想到的最好、最干净、最优化(就逻辑分离和未来代码维护而言)的解决方案。如果有人有更好的想法,我很乐意转给绿色勾号。


第一次尝试回答:

我初步得出结论,没有办法使用可以检测查询字符串何时更新的后台事件侦听器来实现此效果。

相反,因为我确定只需要检查查询字符串:

  • 当页面加载或重新加载时
  • 何时window.history.pushstate被调用

我可以使用以下内容:

window.addEventListener('load', checkQueryString);
Run Code Online (Sandbox Code Playgroud)

window.history.pushState({action : 'myAction'}, document.title, '?action=myAction');

checkQueryString();
Run Code Online (Sandbox Code Playgroud)