共计 1515 个字符,预计需要花费 4 分钟才能阅读完成。
- 设施: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())。