关于 Safari back 按钮在 iOS 16 不能按照期望工作的问题分析

  • 设备: iOS: 16.1.1
  • User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Mobile/15E148 Safari/604.1

问题重现步骤:

  • 使用 iOS 16.1.1 Safari 打开 test1.html
  • 点击 Link 超链接跳转到 test2.html
  • 在 test2.html 回退到 test1.html

期望的结果是看到 alert 对话框。

问题在 iOS 15 不能重现。

test1.html 的源代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Test1</title>
  </head>
  <body>
    <a href="test2.html">Link</a>
  </body>
</html>

test2.html 的源代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Test2</title>
  </head>
  <body>
    <button id="btn">history.back()</button>
    <script>
      history.pushState(null, null, null)

      window.addEventListener("popstate", _ => alert(1))

      document.getElementById("btn").addEventListener("click", _ => {
        history.back()
      }, false)
    </script>
  </body>
</html>

我在好几个浏览器上做了测试:

我刚试过,也可以在 macOS 上重现。

我在单击 history.back() 按钮时看到 alert,但在单击后退按钮(或向后滑动)时看不到 alert。

对于 history.back() 和通过浏览器 UI 向后导航之间的行为差异,我还没有任何解释(尽管我怀疑这与我们所做的一些后退/前进列表劫持预防工作有关)。

我还注意到我们的行为似乎与 Chrome 一致。 因此,如果有错误,那不是 WebKit 特有的。

Firefox 似乎始终如一地显示 alert,正如 Web 开发人员所期望的那样。

StackOverflow 上相关的讨论

结论

哦,我只是更仔细地查看了测试用例,我明白了现在发生了什么。

与 Chrome 类似,WebKit 最近做了一些安全加固,以防止不良的 JavaScript 劫持后退/前进列表。 这意味着由 JS 添加的历史条目(例如通过 history.pushState())在用户导航时会被跳过,除非它们是通过用户交互添加的。

在测试用例中,test2.html 在没有用户交互的情况下调用 history.pushState()。 结果,创建的历史记录项被标记了一个特殊的标志。 如果用户向后滑动或按下后退按钮,我们将跳过这个“虚拟”历史记录项,因此不会触发 popstate 事件。 这是新的故意行为,应该与 Blink 保持一致。

如果不希望跳过历史记录项,则在调用 history.pushState() 时需要用户手势/激活(例如,由于用户单击按钮而调用 history.pushState())。


Jerry Wang的SAP技术专栏
SAP成都研究院开发专家,SAP社区导师,SAP中国技术大使
868 声望
1.6k 粉丝
0 条评论
推荐阅读
SAP Corbu Theme 在浏览器和 SAPGUI 应用中的使用场景
SAP Corbu Theme 是一种清新、现代且独特的视觉标识。 它以瑞士建筑师兼设计师 Charles-Édouard Jeanneret,又名 Le Corbusier 的名字命名。 该设计有意保持中立,以与各种遗留内容(Legacy content)融为一体。

JerryWang_汪子熙阅读 788

封面图
从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木140阅读 11.9k评论 10

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木60阅读 5.9k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.1k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木39阅读 7k评论 6

CSS 绘制一只思否猫
欢迎关注我的公众号:前端侦探练习 CSS 有一个比较有趣的方式,就是发挥想象,绘制各式各样的图案,比如来绘制一只思否猫?思否猫,SegmentFault 思否的吉祥物,是一只独一无二、特立独行、热爱自由的(&gt;^ω^&lt...

XboxYan41阅读 2.8k评论 14

封面图
还在用 JS 做节流吗?CSS 也可以防止按钮重复点击
举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如只允许每300ms提交一次,这时候我想大部分同学都会到网上直接拷贝一段throttle函数,或者直接引用lodash工具库

XboxYan34阅读 2.2k评论 2

封面图
868 声望
1.6k 粉丝
宣传栏