乐趣区

关于javascript:页面加载时使用脚本自动跳转到新页面移动端浏览器不会产生历史记录

最近遇到这样一个需要:

  • 关上以后页面时,可能会带上一个参数pid
  • 页面初始化时,如果发现存在此参数,就立即跳转到其对应的内部页面。
  • 当用户从内部页面后退时,能够回到以后页面,此时失常显示页面内容。

我的实现形式是:

  • hash 传递pid
  • 在页面入口脚本中,如果 hash 中没有pid,就失常渲染页面。
  • 如果发现存在 pid,就不渲染页面内容,而是通过ajax 从后盾获取 pid 对应的 URL。而后从 location.hash 里去掉 pid,再批改location.href 进行跳转。

在 PC 端 Chrome 下测试失常通过,但在手机浏览器中呈现了问题。

跳转到新页面后,按后退时不会回到当前页。在微信浏览器里,后退会间接敞开,在小米自带浏览器、夸克浏览器里,后退会回到标签页的初始页,挪动端 Chrome 还是失常。

上百度搜了下,尝试了以下计划,均有效:

  • setTimeout 延时再跳转
  • 应用 location.assign() 代替 location.href 赋值
  • 应用 history.pushState 手动写入以后页面 URL 后再跳转
  • window.onload 里执行判断并延时跳转
  • window.onload 里延时执行一个模仿点击事件并在该元素的点击回调中执行跳转

这其中倒是发现一个奇怪的景象,就是在延时跳转前,如果手动点击过页面任意地位,体现就会一切正常,新页面后退能够失常返回当前页,完全符合需要预期。

然而,应用 dispatchEvent 模仿进去的点击事件不行。

与之前做全屏 api 时遇到的问题相似,应该是浏览器有某种策略,要求 history 的操作只能在用户的实在点击操作中执行。

但奇怪的是搜了很多中文页,没有一个提到这样的问题。

最初在 StackOverflow 上找到了一些解答(相似问题同样很少,但总算有答案):

HTML 规范 文档对 history 的应用有一些标准:

If any of the following conditions are met, let replacement flag be unset; otherwise, let it be set:

  • This Location object’s relevant Document has completely loaded, or
  • In the task in which the algorithm is running, an activation behavior is currently being processed whose click event’s isTrusted attribute is true, or
  • In the task in which the algorithm is running, the event listener for a click event, whose isTrusted attribute is true, is being handled.

大抵的意思是:

如果满足以下任意条件之一,location对象的 replacement 标记置为默认,否则置为 true。

(换句话说,如果不满足以下条件,对 location 进行任何操作,都不会产生新的历史记录)

  • location对象所在的文档曾经 齐全加载
  • location的批改操作由 click 事件触发,且事件的 isTrusted 属性为true(也就是用户的实在点击操作)

英文不行,没有找到 齐全加载 的准确定义。但我揣测对遵循 HTML 规范的浏览器来说,只有用户与页面产生互动,才示意页面真的曾经“齐全加载”了。

在用户对页面进行操作前,只有最终展示的页面才被认为是无效页面,之前的所有两头跳转都应该被疏忽,不计入历史记录,这样能力防止后退行为呈现死锁。

我对这种设计示意了解,这段 HTML 规范的定义证实了我的揣测。因而,本来料想的计划是走不通的,我只能调整需要了。

最终计划是减少一个跳转两头页,由用户点击来进行跳转。

话说 Chrome 没这个问题,阐明 Chrome 在这一条上其实没有遵循 HTML 标准规范?

退出移动版