2011-05-17 57 views
4

在Safari中,如果加載了iframe,並且用戶通過後退或前進來更改歷史記錄狀態,則不會觸發popstate事件,從而導致應用程序狀態和窗口位置不同步。爲什麼Safari在加載iframe時未觸發popstate?

我認爲一個活躍的XHR請求會導致相同的行爲,但我還沒有能夠確認。

這裏有一個的jsfiddle,讓您可以輕鬆地重現該問題: http://jsfiddle.net/neonsilk/muHk8/

您只需要點擊鏈接/按鈕的順序,從1至6

在Safari 5.0.5,輸出爲:

(逆時間,重要的部分是在頂部的狀態相比)

[1305665493096]/
[1305665493096] vs 
[1305665493096] /node 
--------------- 
[1305665489955] iframe loaded 
--------------- 
[1305665489806] (did popstate or $.address change trigger?) 
[1305665489805] called history.back() 
[1305665489805] appended iframe 
--------------- 
[1305665488428] popstate: /node 
[1305665488427] $.address change: /node 
--------------- 
[1305665487821] popstate:/
[1305665487821] $.address change:/
--------------- 
[1305665487179] $.address change: /node 
--------------- 
[1305665486606] $.address change:/
--------------- 
[1305665485732] iframe loaded 
--------------- 
[1305665485569] $.address change: /neonsilk/muHk8/show/ 
[1305665485568] $.address init 

然而,在瀏覽器(11)或Firefox(4.0),輸出的樣子:

(注意,狀態是同步)

[1305665609499]/
[1305665609499] vs 
[1305665609499]/
--------------- 
[1305665608360] iframe loaded 
--------------- 
[1305665607770] popstate:/
[1305665607770] $.address change:/
[1305665607758] (did popstate or $.address change trigger?) 
[1305665607758] called history.back() 
[1305665607758] appended iframe 
--------------- 
[1305665606870] popstate: /node 
[1305665606869] $.address change: /node 
--------------- 
[1305665606150] popstate:/
[1305665606149] $.address change:/
--------------- 
[1305665605551] $.address change: /node 
--------------- 
[1305665604808] $.address change:/
--------------- 
[1305665603354] iframe loaded 
--------------- 
[1305665602688] $.address change: /neonsilk/muHk8/show/ 
[1305665602682] $.address init 
[1305665602676] popstate: /neonsilk/muHk8/show/ 

這是在Safari中的錯誤?如果是的話,有沒有人發現一種解決方法?

(這也是有趣的是,Firefox和Chrome的火popstate事件在頁面加載)。

回答

1

更新

此錯誤是,據我所知,first reported by Ben Cherry

以下是來自WebKit的相應的bug reportchangeset

而且the issue from Chromium

當錯誤是固定在Chrome中我一直無法弄清楚。如果其他人有,我將不勝感激的信息。

我不知道錯誤在WebKit的533.21.1存在(這是Safari瀏覽器5.0.5使用),並已被(夜間野生動物園/ WebKit的)固定由534.36 - 但我不知道,和避風港無法弄清楚,哪個中介製造商引入了這個解決方案。

a helpful chart將Chrome版本映射到其WebKit版本。

最重要的,當有任何積極網絡流量(圖片加載,Ajax請求,等等),而不是僅僅I幀這個bug apprently發生。如果您嘗試實施History API支持,或者您正在使用最新版本的Asual's jQuery Address plugin(其默認情況下啓用了歷史記錄支持),則此錯誤可能會嚴重影響您的應用程序。


月2日更新

我想我找到了這裏介紹的修復確切的WebKit版本(534.10)。所以,如果你正在使用jQuery和Asual的地址插件,這裏的切實可行的解決辦法:

if (!($.browser.webkit === true && parseFloat($.browser.version) < 534.10)) { 
    // only enable state support if WebKit version >= 534.10 
    $.address.state("/base/path"); 
} 

我希望這可以幫助別人!


我只是測試的小提琴在最新的WebKit每日(r86671),並且狀態保持同步,所以它必須是一個錯誤。有趣的是,如何花費大量時間撰寫問題並立即提交問題就能激發答案。

不過,如果有人有解決方法,將不勝感激。

WebKit每日(r86671):

[1305666598481]/
[1305666598481] vs 
[1305666598480]/
--------------- 
[1305666597469] iframe loaded 
--------------- 
[1305666597300] popstate:/
[1305666597298] $.address change:/
[1305666597270] (did popstate or $.address change trigger?) 
[1305666597269] called history.back() 
[1305666597269] appended iframe 
--------------- 
[1305666596605] popstate: /node 
[1305666596605] $.address change: /node 
--------------- 
[1305666596008] popstate:/
[1305666596008] $.address change:/
--------------- 
[1305666595555] $.address change: /node 
--------------- 
[1305666595142] $.address change:/
--------------- 
[1305666578600] iframe loaded 
--------------- 
[1305666578400] $.address change: /_display/ 
[1305666578400] $.address init 
--------------- 
[1305666577964] popstate: /_display/ 

同樣有趣的是Safari瀏覽器現在匹配Chrome和Firefox的行爲,在頁面加載射擊popstate。

1
  1. img/script/iframe加載將打破popstate,但XHR不受此bug的影響!
  2. 後退/前進文件加載將被延遲。加載時我們會得到一個popstate。 (只有最後狀態將被彈出,即使有多個前進/後退)

(的Android 2.2和Safari瀏覽器下測試在iOS 4.3.3)

因此,解決方法是:

使用XHR,而不是img,用於跟蹤/預載任何加載事件。

如果用戶在加載事件之前進行了兩次或多次後退/前進,但如果加載時間很短並且由於最終狀態正確,所以我認爲沒關係,用戶很少會執行多個操作。

而另一個解決辦法是:

,如果它不popstate改變觀看使用定時器的URL,自己做骯髒的工作。 (作爲這個bug的評論,Facebook曾經使用這個解決方案。)

但是這種方法太複雜了,因爲你應該將狀態序列化/反序列化爲url或localstorage/sessionstorage,就像你沒有History API 。所以我不認爲這是一個可接受的解決方法。

相關問題