我们在单页应用程序中进行了一项调查。因为这是一项调查,我们希望允许用户回溯而不是前进历史。也就是说,如果他们改变“过去”的答案,可能会影响未来的问题,所以规则是:你可以向后旅行,但只能实时前进。
由于其本质,使用
history.pushState
和 popstate
处理程序并不是我们想要的。实际上,我们希望在浏览器的后退按钮上有一个事件侦听器,同时选择阻止或允许“自然”浏览器的功能。
我已经尝试了一些解决方案,它们几乎完成了我想要的一切,除了它们似乎在 Safari 中不起作用。显然,Safari 是新的 IE。我已经尝试过这些基本代码片段:
window.history.pushState(null, null, document.URL);
window.addEventListener('popstate', () => {
// This is simplified, obviously...
if (onFirstPageOfSurvey) {
// beacuse we start by pushing on the history stack, we have to go back
// 2 steps to allow the user to go back to the actual previous page.
history.back(2);
} else {
// pushing right back on to the history after popping should
// keep the page from navigating away (just not in safari)
window.history.pushState(null, null, document.URL)
}
})
我已经尝试了上述的多种变体,但不可能全部列出。
这个似乎有点过时了,但在 Chrome 中仍然可以工作,但同样不能在 Safari 中工作
function noBack() {
window.history.forward()
}
noBack()
window.onload = noBack
window.onpageshow = function (evt) {
if (evt.persisted) noBack()
}
window.onunload = function () {
void 0
}
如有任何帮助,我们将不胜感激!
我知道这是一个敏感的用户体验主题。目标基本上是允许后退按钮在应用程序内返回,然后如果他们一路退出,让浏览器历史记录接管并实际返回页面。我们并不是想“诱骗”用户;我们只是想“诱骗”用户。相反,我们发现用户倾向于认为他们可以使用后退按钮,一旦他们顺利进入调查,他们就会非常沮丧,然后最终进入调查之前的页面,基本上失去了一切。
发布到 SO 对我来说就像橡皮鸭一样......我在写作时想到了一些事情,现在实际上已经有了解决方案。
我认为问题是 Safari 不喜欢即时的
pushState
。经过仔细检查,从 home => sruvey 导航会导致我的 Chrome 历史记录看起来像这样(顶部是最新的):
...条目 #2 是初始导航,条目 #1(最新的)是第一个
pushState
的结果。在 Safari 中,完全相同的导航看起来就像
解决方案:
推迟
pushState
直到浏览应用程序。声明一个标志,使其仅被调用一次。我感觉它可能需要与 Safari 中的用户事件相关联。在页面加载时使用 setTimeout
不起作用。
简化示例:
window.addEventListener('popstate', () => {
if (onFirstPageOfSurvey) {
history.back(2);
} else {
window.history.pushState(null, null, document.URL)
}
})
let backButtonControlled = false;
function navigateThroughSurvey(surveyState) {
// Do things with surveyState that we're not concerned about right now...
if (!backButtonControlled) {
window.history.pushState(null, null, document.URL);
backButtonControlled = true;
}
}