2011-11-03 30 views
17

tl; dr - iOS 5上的Safari緩存太難了,它正在破壞我的網站。iOS 5中的頁面緩存問題瀏覽器返回/卸載事件未觸發時

我很擔心iOS 5中的Safari瀏覽器處理後退前進緩存,他們稱之爲「頁面緩存」。描述方式here很好地解釋了這種行爲。

很簡單,頁面緩存使得它如此,當你離開一個頁面,我們「暫停」它,當你回來,我們按「播放」。

這是造成整個我的網站的問題。當使用後退按鈕時,大多數其他瀏覽器會向您顯示處於加載狀態的頁面。不是iOS 5上的Safari,它會向您顯示最後一次離開的頁面。一個簡單的例子就是禁用提交按鈕。如果我使用Javascript來禁用提交按鈕,然後提交表單,當你點擊提交按鈕時仍然會被禁用。這在其他瀏覽器(包括Safari的桌面版)中一直存在問題,但可以通過將onload事件處理程序設置爲空白函數來解決。我相信這告訴瀏覽器使緩存失效,因爲在該函數中可能發生了重要的事情。此攻擊似乎不適用於iOS 5上的Safari。

下面是將問題歸結爲裸露要領。當你加載test.html時,你會看到文本「原始文本」。當你點擊鏈接時,該文本將變爲「更改文本 - 轉發到下一頁」,然後在3秒內你將被轉發到test2.html。在所有瀏覽器中,所有這一切都很好。在所有其他瀏覽器中,當您單擊後退按鈕時,您將看到的文本是「原始文本」,但在Safari 5 for iOS 5中,您將看到「更改文本 - 轉發到下一頁」。

有關如何處理此問題的任何建議?

這是一個簡單的例子

的test.html

<script> 
function changeText() { 
    el = document.getElementById("text"); 
    el.innerHTML = "Changed text - forwarding to next page"; 
    setTimeout("forward()",3000);  
} 
function forward() { 
    document.location.href = "test2.html"; 
} 
</script> 
<div id="text">Original Text</div> 
<a href="Javascript:changeText()">Click Here</a> 
<script> 
window.onunload = function(){}; 
</script> 

test2.html

<div>Click back button</div> 

這是使用一個柱形式的第二個例子。這是我的應用如何工作的一個簡單例子。當您導航回formtest2.asp時,您應該看到發佈的表單值和div文本應該是原始的。

formtest.asp

<form method="post" action="formtest2.asp"> 
    Test: <input type="text" name="test"/> 
    <input type="submit" value="Submit"/> 
</form> 

formtest2.asp

<script> 
function changeText() { 
    el = document.getElementById("text"); 
    el.innerHTML = "Changed text - forwarding to next page"; 
    setTimeout("forward()",3000);  
} 
function forward() { 
    document.location.href = "test2.html"; 
} 
</script> 

<% 
Dim test 
test = Request("test") 
Response.Write("Test value: " & test & "<br />") 
%> 

<div id="text">Original Text</div> 
<a href="Javascript:changeText()">Click Here</a> 
<script> 
window.onunload = function(){}; 
</script> 

test2.html

<div>Click back button</div> 
+0

只需要更多的信息。看起來好像我測試過的所有瀏覽器(Firefox,IE,Safari Desktop)都按照該順序觸發了頁面隱藏並卸載。 iOS 5上的Safari僅觸發頁面隱藏。 – Clarke

+0

當打開一個新選項卡時,unload事件不會被觸發,只是頁面隱藏。當打開一個新標籤頁時,您會希望能夠回到舊標籤頁並按照您離開的頁面查看頁面。問題是,當我們在同一個標​​籤頁/窗口中從一個頁面導航到另一個頁面時,應該根據w3c觸發卸載事件,但不是。 http://www.w3.org/TR/DOM-Level-2-Events/events.html。 「卸載事件發生在DOM實現從窗口或框架移除文檔時,此事件對於BODY和FRAMESET元素有效。」 – Clarke

+0

任何使用location.reload()的解決方案都會失敗,因爲對於此功能,ios 5上的Safari只會執行GET,而不是像所有其他瀏覽器一樣執行POST。 – Clarke

回答

1

我滿足了同樣的問題。
在iOS4上,當您將homepage.html導航到2.html,然後返回homepage.html時,將調用js 不會調用。當您將homepage.html導航到2.html時,從2.html繼續到3.html,然後從3到2回到首頁,JS 將被調用爲!是的,這太可怕了!
但在iOS5的MobileSafari,它始終不能被稱爲:(這也許是對的iOS5緩存錯誤。我在iOS 5.0.0和5.0.1進行測試,得到了相同的結果。

但是,當你實現onUnload事件body元素,它可以解決前面的MobileSafari上的前向問題 我只是在homepage.html中將<body>更改爲<body onUnload="">,然後從主頁更改爲2.html,當返回主頁時,主頁上的javascript將被調用。它適用於FF,桌面Safari,移動Safari(iOS4

因此,我們如何在iOS5上做?不幸的是,我還沒有找到解決方案。但我的web應用程序在本地客戶端上運行,我從本地添加reload()呼叫固定的:

 
     if (isOS5_) 
     { 
      [webView stringByEvaluatingJavaScriptFromString:@"location.reload();"]; 
     } 

webViewDidFinishLoad:

+0

我嘗試在導航回頁面時在頁面上添加重新加載,但這會導致期望表單帖子的頁面出現問題。重新加載只需加載URI而不發佈表單數據。 – Clarke

1

我的手機網站,我有固定的這個小JS代碼的問題:

if ((/iphone|ipad.*os 5/i).test(navigator.appVersion)) { 
    window.onload=function() { 
     localStorage.setItem("href",location.href); 
    }; 
    window.onpopstate=function() { 
     var a=localStorage.getItem("href"), 
      b=location.href; 
     if (b!==a&&b.indexOf((a+"#"))===-1) { 
      document.body.style.display="none"; 
      location.reload(); 
     } 
    }; 
} 

場景:

點擊來自「第一頁」鏈接「第2頁」:一旦點擊「第1頁」靠攏d, 「Page2」被加載並觸發onload和許多其他事件。

[第1頁] - >點擊鏈接 - > [第2頁] - > onload事件 - > onpopstate - > ...

在這一點上,如果你點擊瀏覽器上的後退按鈕,「第2頁」獲得 關閉並且「Page1」被加載並觸發onload和許多其他事件。

[第2頁] - >單擊後退按鈕 - > [第1頁] - > onload事件 - > onpopstate - > ...

點擊在IOS5後退按鈕使得關「第一頁」和「第2頁」出現但是 頁面未加載,視口比例損壞,唯一激發的事件 是onpopstate。

- >點擊後退按鈕 - > [第1頁] - > onpopstate。

解決方法:

圍繞事件的onload,onpopstate和localStorage的對象的修復工程。

onload是腳本管理的第一個事件,在此範圍內它存儲當前location.href在localStorage上的 。

如果沒有任何bug,在onpopstate中當前的location.href和存儲的必須是相同的,腳本不應該做任何事情。

在IOS5上使用Safari時,頁面未加載且onload事件未被觸發,則 location.href和存儲的href在onpopstate事件中不同。

在這種情況下,只隱藏當前頁面(對於與 相關的視口中的另一個bug),並用位置對象重新加載頁面。

+0

感謝您的意見,但它不適合我。由於這適用於您,您可能需要將ipod添加到if語句。我必須這樣做,因爲iPod Touch是我用來測試的,並且必須添加它才能使其工作。此解決方案適用於動態內容頁面,但在導航回期望提交表單的頁面時會失效。 location.reload()只加載該URI並且不會發布原始表單值。這是我上面的示例html不完整的地方。 – Clarke

26

我還在尋找同一問題的答案。回到iOS 5不會執行任何JavaScript,只會將頁面保留在您離開或重定向時的上一個狀態。

嘗試在「Is there a cross-browser onload event when clicking the back button?」中找到的奇怪的「onunload」黑客只適用於iOS 4,而不是iOS 5,它不會按預期調用該事件。 Nickolay指出web-kit上的新功能叫做「pageshow」和「pagehide」,它比Giuseppe的例子更可靠。

  1. 你需要從這篇文章黑客:「Is there a cross-browser onload event when clicking the back button?」這個iOS中4
  2. 使用來解決這個腳本,它使用了新的事件安全檢查,如果頁面是從緩存中加載並強制重裝(避免的URL檢查和本地存儲,也包括iPod播放器)的iOS 5:

    <body onunload=""> 
    ... 
    <script type="text/javascript"> 
    if ((/iphone|ipod|ipad.*os 5/gi).test(navigator.appVersion)) { 
        window.onpageshow = function(evt) { 
        // If persisted then it is in the page cache, force a reload of the page. 
        if (evt.persisted) { 
         document.body.style.display = "none"; 
         location.reload(); 
        } 
        }; 
    } 
    </script> 
    
+0

最後,這個解決方案和其他的一樣,重新加載並不能解決我的問題。從下面開始,「這個解決方案適用於動態內容頁面,但當您回到期望提交表單的頁面時,它會失效。location.reload()僅加載該URI並且不會發布原始表單值。」 – Clarke

+1

@Clarke:您需要使用服務器端代碼將您想要重新POST的POST參數寫入標記(就像您寫出「test」變量的方式一樣)。爲所有想要再次POST的變量在表單元素下注入隱藏的輸入元素。然後使用上面相同的基本代碼,而不是重新加載,只需進行表單提交。 – BrutalDev

+0

這似乎是一個很好的解決方案,但在現實中並非如此。有時這種事件有時不會發生。我什至不能解釋如何重複這個問題,嘗試打開頁面1,然後頁面2,然後點擊返回,事件觸發,然後重複幾次。 – Rantiev

0

找到如何避免這個問題(一個或多個)之一後,我們都似乎對這個問題,我艱難的我'd想分享:)

在閱讀了關於該主題的一些相關主題後,主要討論堆棧溢出「最熱門主題」,處理「Page Cache」(http://www.webkit.org/blog/427/webkit-page-cache-i-the-basics/http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/),檢查「卸載」事件(developer.apple.com/library/IOS /ipad/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)/「pageshow」nohing必須處理其先前狀態(而不是前一頁INITIAL狀態)中的簡短「頁面幽靈」,而只是頁面因爲它被留下),而用戶切換回應用程序/或解鎖他的設備/或退出後返回到應用程序。

看來(對我來說,至少),這個「看得見的頁故障」當時我做了iOS6的更新,解決了像5分鐘前; d

當時我能夠用我的web應用程序中移動Safari瀏覽器,並將其添加到主屏幕後,在「應用程序切換」或「重新啓動」情況下(具有或不具有清除緩存)的行爲與第一次啓動相同:您看到一個BLANK頁面,然後內容(可能是與保存到主屏幕的url對應的頁面,或者使用localStorage加載的任何其他內容,例如[my case(..)])。

對於我能夠捕捉到的事件,IOS4 IOS5設備無法設法擺脫那種「視覺持久性毛刺」。我想這是因爲「頁面緩存」的工作方式,但現在我在iPad上運行IOS6,因爲故障不再存在,我猜Safari團隊必須改進他們處理「主屏幕」webapps的方式(.. )

相關問題