3

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

 1 year ago
source link: https://mirari.cc/2020/07/01/%E9%A1%B5%E9%9D%A2%E5%8A%A0%E8%BD%BD%E6%97%B6%E4%BD%BF%E7%94%A8%E8%84%9A%E6%9C%AC%E8%87%AA%E5%8A%A8%E8%B7%B3%E8%BD%AC%E5%88%B0%E6%96%B0%E9%A1%B5%E9%9D%A2%E7%A7%BB%E5%8A%A8%E7%AB%AF%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B8%8D%E4%BC%9A%E4%BA%A7%E7%94%9F%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

2020-07-01 学习笔记

1 1.6k 1 分钟

最近遇到这样一个需求:

  • 打开当前页面时,可能会带上一个参数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标准规范?


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK