共计 1588 个字符,预计需要花费 4 分钟才能阅读完成。
最近遇到这样一个需要:
- 关上以后页面时,可能会带上一个参数
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 relevantDocument
has completely loaded, or- In the task in which the algorithm is running, an activation behavior is currently being processed whose
click
event’sisTrusted
attribute is true, or- In the task in which the algorithm is running, the event listener for a
click
event, whoseisTrusted
attribute is true, is being handled.
大抵的意思是:
如果满足以下任意条件之一,location
对象的 replacement
标记置为默认,否则置为 true。
(换句话说,如果不满足以下条件,对 location
进行任何操作,都不会产生新的历史记录)
location
对象所在的文档曾经齐全加载
location
的批改操作由click
事件触发,且事件的isTrusted
属性为true
(也就是用户的实在点击操作)
英文不行,没有找到 齐全加载
的准确定义。但我揣测对遵循 HTML 规范的浏览器来说,只有用户与页面产生互动,才示意页面真的曾经“齐全加载”了。
在用户对页面进行操作前,只有最终展示的页面才被认为是无效页面,之前的所有两头跳转都应该被疏忽,不计入历史记录,这样能力防止后退行为呈现死锁。
我对这种设计示意了解,这段 HTML 规范的定义证实了我的揣测。因而,本来料想的计划是走不通的,我只能调整需要了。
最终计划是减少一个跳转两头页,由用户点击来进行跳转。
话说 Chrome 没这个问题,阐明 Chrome 在这一条上其实没有遵循 HTML 标准规范?