JS:回退至初始页面加载前时popstate事件异常问题排查
用pushState/popState做历史记录,后退要多点击一次才离开?我来给你捋清楚!
问题回顾
你说自己用pushState和popState实现JS历史记录功能,前进后退都正常,但退到初始页面加载前的时候,得多点击一次后退按钮才能离开页面,对吧?
先看看你贴的代码片段:
function action(text) { history.pushState({"text":text}, text); doAction(text); } function doAction(text) { $('span').text(text); } var $button = $('button'); var $p = $('p'); $p.hide(); action("foo"); $button.on('click', function() { // 这里应该是触发切换内容的逻辑,比如点一下换个文本 action("bar"); });
为啥会多这一下?
其实问题出在你页面初始化时调用的action("foo")上!
咱们来掰扯清楚浏览器的历史记录逻辑:
- 当页面第一次加载完成时,浏览器已经自动给你创建了一条初始历史记录(就叫它「初始页」吧)。
- 结果你刚加载完就调用
action("foo"),这个函数里又执行了history.pushState——相当于在「初始页」的后面又加了一条新的历史记录(就叫它「foo页」)。
这时候浏览器的历史栈是这样的:[初始页, foo页]
那你点后退按钮的时候:
- 第一次点:从「foo页」退回到「初始页」(这时候页面看起来是初始状态,但其实还在当前页面的历史里)
- 第二次点:才会从「初始页」真正离开当前页面
这就是为啥你得多点一次的原因!
怎么解决?
核心思路就是:页面初始化的时候,别用pushState加历史记录,直接渲染初始状态就行,只有后续用户操作(比如点按钮)的时候,再用pushState添加新的历史条目。
给你改了下代码,你参考下:
function action(text) { // 只有非初始化的操作,才添加历史记录 if (history.state && history.state.text !== text) { history.pushState({"text":text}, text); } doAction(text); } function doAction(text) { $('span').text(text); } var $button = $('button'); var $p = $('p'); $p.hide(); // 初始化页面:直接调用doAction渲染,不碰pushState doAction("foo"); $button.on('click', function() { action("bar"); }); // 别忘了监听popState,处理浏览器的前进后退 window.addEventListener('popstate', function(e) { if (e.state) { // 从历史记录里取出状态,更新页面 doAction(e.state.text); } else { // 回到最开始的初始状态,重新渲染foo doAction("foo"); } });
这样调整后,初始加载时不会额外添加历史记录,历史栈就只有浏览器默认的那一条初始记录,后续点击按钮才会新增条目,后退的时候就不用多点那一下啦!
内容的提问来源于stack exchange,提问作者lilalinux
相关产品推荐
相关产品推荐

