最近遇到这样一个需要:

  • 关上以后页面时,可能会带上一个参数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标准规范?