[英]The Safari Back Button Problem
我為當地社區大學做一些小程序和網絡工作。 工作包括維護一個非常大的破壞靈魂的網站,該網站由一堆 VBScript、javascript、Dreamweaver 生成的 cruft 和一系列附加組件組成,多年來,各種騙子說服他們購買。
幾天前,我接到一個電話“該網站正在為使用 Safari 的人鎖定!” 好的,第一步下載Safari(v3.1.2),第二步瀏覽網站。 一切似乎都運行良好。
長話短說,我終於解決了這個問題,它與 Safari 的后退按鈕有關。 該網站使用花哨的 javascript 菜單,該菜單適用於我第一次嘗試過的所有瀏覽器,包括 Safari。 但是在 Safari 中,如果您點擊頁面外的鏈接,然后點擊后退按鈕,菜單將不再有效。
我做了一個精簡的網頁來說明原理。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head><title>Safari Back Button Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body onload="alert('Hello');">
<a href="http://www.codinghorror.com">Coding Horror</a>
</body>
</html>
加載頁面,您會看到警報框。 然后點擊頁面上的鏈接並點擊后退按鈕。 在 IE 和 Firefox 中,您會再次看到警告框,而在 Safari 中則不會。
經過激烈的谷歌搜索,我發現其他人也有類似的問題,但沒有真正令人滿意的答案。 所以我的問題是,在用戶點擊后退按鈕后,如何讓我的頁面在 Safari 中以與在其他瀏覽器中相同的方式工作?
如果這是一個愚蠢的問題,請保持溫和,javascript 對我來說有點陌生。
Stefan 的 iframe 解決方案有效,但如果這還不夠優雅,我發現以下 JavaScript 也可以解決它:
window.onunload = function(){};
也就是說,如果您的菜單是 JavaScript,那么您可能更喜歡用 JavaScript 解決這個問題。
卸載事件處理程序定義的想法來自這篇 Firefox 1.5 文章: https : //developer.mozilla.org/en/Using_Firefox_1.5_caching 。
把它放在 body 標簽<body onunload="">
每次點擊返回按鈕時,這將強制 safari、chrome、FF 重新加載
這是 Mobile Safari 的一個很好的解決方案:
/*! Reloads page on every visit */
function Reload() {
try {
var headElement = document.getElementsByTagName("head")[0];
if (headElement && headElement.innerHTML)
headElement.innerHTML += " ";
} catch (e) {}
}
/*! Reloads on every visit in mobile safari */
if ((/iphone|ipod|ipad.*os 5/gi).test(navigator.appVersion)) {
window.onpageshow = function(evt) {
if (evt.persisted) {
document.body.style.display = "none";
location.reload();
}
};
}
(來源)
我根據我的需要修改了它,但它是可以的。 (如果您不修改它,刷新時會出現煩人的白屏)。
請不要遵循任何告訴您忽略緩存的建議。 頁面被緩存是有原因的——為了改善用戶體驗。 您使用的方法會使用戶體驗變得更糟,所以除非您討厭您的用戶,否則不要這樣做。
Safari(桌面和 iOS)的正確解決方案是使用pageshow
事件而不是onload
事件(有關這些事件的信息,請參閱https://developer.mozilla.org/en-US/docs/Using_Firefox_1.5_caching )。
pageshow
事件將在您期望onload
事件觸發的同時觸發,但當頁面通過緩存提供時它也將起作用。 無論如何,這似乎是您想要的。
iframe 解決了這個問題:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head><title>Safari Back Button Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body onload="alert('Hello');">
<a href="http://www.codinghorror.com">Coding Horror</a>
<iframe style="height:0px;width:0px;visibility:hidden" src="about:blank">
this prevents back forward cache
</iframe>
</body>
</html>
更多細節
我注意到一些非常相似的事情。 我認為這是因為 Firefox 和 IE 在返回時再次從服務器檢索頁面,而 Safari 則沒有。 您是否嘗試過添加頁面到期/無緩存標頭? 當我發現這種行為時,我打算調查它,但還沒有時間。
我知道這個線程已經有一年了,但我只是使用 ProjectSeven 的 Safari 后退按鈕修復了一個相同的 Safari 唯一問題。 奇跡般有效。
http://www.projectseven.com/extensions/info/safaribbfix/index.htm
在 iPad 上遇到了同樣的問題。
不是那么漂亮,但它有效:)。 這個怎么運作。
我意識到在 iPad Safari 上,按下后退按鈕時不會重新加載頁面。 我每秒在頁面上放置一個計數器並保存當前時間戳。
當頁面加載時,計數器和時間是同步的。 在后退按鈕上,計數器在它停止的地方繼續,時間戳和計數器之間存在差距。 如果差距大於 500 毫秒,則強制重新加載頁面。
在文件 action.js 中
var showLoadingBoxSetIntervalVar;
var showLoadingBoxCount = 0;
var showLoadingBoxLoadedTimestamp = 0
function showLoadingBox(text) {
var showLoadingBoxSetIntervalVar=self.setInterval(function(){showLoadingBoxIpadRelaod()},1000);
showLoadingBoxCount = 0
showLoadingBoxLoadedTimestamp = new Date().getTime();
//Here load the spinner
}
function showLoadingBoxIpadRelaod()
{
//Calculate difference between now and page loaded time minus threshold 500ms
var diffTime = ( (new Date().getTime()) - showLoadingBoxLoadedTimestamp - 500)/1000;
showLoadingBoxCount = showLoadingBoxCount + 1;
var isiPad = navigator.userAgent.match(/iPad/i) != null;
if(diffTime > showLoadingBoxCount && isiPad){
location.reload();
}
}
嘗試這個
如果(性能。導航。類型== 2){
警報(“你好”);
}
在我的 Angular 應用程序中,我使用這個條件來解決這個問題。 首先,我在下面的index.html
添加了onunload=""
事件句柄
<body class="mat-typography" onunload="">
<app-root></app-root>
</body>
然后在我的組件ngOnInit
方法中,我添加了如下代碼
public ngOnInit(): void {
window.onpageshow = (event) => {
if (event.persisted) {
document.body.style.display = "none";
location.reload();
}
};
...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.