2016-11-21 105 views
2

我在我的JS/ReactJS應用程序中添加了一個beforeunloadas customary事件列表器。該功能根據內部狀態unSaved添加確認對話框。* onbeforeunload *緩存在Safari(macOS)上?

在Chrome和Firefox(macOS/desktop)上一切正常。

在Safari瀏覽器,但是:

  • 第一次「我使用」的事件處理程序(我離開,而unSaved==true頁),它工作正常的aspected,
  • 然而,在隨後的嘗試離開頁面unSaved==true,Safari不會要求任何確認。
  • 當我去到一個新的標籤(與以前同樣的網址),再次在第一時間的作品,隨後的時間不...

什麼是怪異:我可以看到我添加的事件功能實際上每次在Safari上都會被調用,因爲每次都會打印一個測試console.log

我唯一可能的猜測是,Safari以某種方式緩存我對該選項卡的確認響應? (?)

如何解決這個問題的任何想法?

我的堆棧:

Safari: Version 10.0.1 (12602.2.14.0.7) macOS: 10.12.1 (16B2657) host: localhost protocols: tested on both, http and https

更多信息:

  • 事件pageshow有屬性persisted始終設置爲false。因此,Safari的頁面緩存(BFCache)不應該是問題的原因。
+0

由於關閉標籤之前的「確認」在惡意網站上很常見,您可能會遭遇反惡意軟件防護。 – ssube

+0

@ssube你的意思是Safari將我重複的確認嘗試解釋爲惡意軟件行爲,因此只是忽略了我的邏輯? - Chrome和Firefox添加到確認彈出複選框,以供用戶決定_「防止此頁面創建額外的對話」_,這當然是非常明智的。 - Safari不提供這樣的選項嗎? – juanmirocks

+0

我不確定Safari的行爲,但聽起來像一個類似的功能可能會破壞你的代碼。如果你曾經看到過一個頁面反覆打開對話框來阻止用戶離開,大多數瀏覽器都有一些防範措施。如果Chrome和FF做得很好,那麼Safari很可能會做一些陰暗和不幸的事情。 – ssube

回答

1

似乎是Safari的後退/前進緩存問題。該緩存(也稱爲BFCache或頁面緩存)存儲整個網頁的當前狀態,包括JavaScript代碼狀態,並在用戶按瀏覽器的「後退」按鈕時恢復該狀態。你可以閱讀關於它here。通常,當beforeunload用於加載的網頁瀏覽器時,會關閉BFCache。但是,您的JavaScript代碼中可能會有些東西阻止了這種行爲。或者,也許你設置了unSaved state = false然後它被緩存?手動嘗試通過您的網頁上添加解決方法關閉前進/後退緩存:

window.onpageshow = function(event) { 
    if (event.persisted) { 
     window.location.reload() 
    } 
}; 
+0

非常感謝@Sergey。您的答案和額外提供的解決方案可能會解決我的問題!我稍後再報告。 – juanmirocks

+0

非常感謝您。不幸的是,這並沒有解決我的問題。請參閱:http://stackoverflow.com/questions/40727989/is-onbeforeunload-cached-on-safari-macos#comment69049563_40896361 - 你有任何其他想法?謝謝:) – juanmirocks

2

問題

你的問題是由瀏覽器的功能引起的稱爲背向前緩存(BFCache)

當用戶導航時,應該保存頁面的完整狀態。這個想法是當用戶導航返回按鈕頁面可以很快從緩存加載。

Chrome和Firefox將beforeunload事件上的事件處理程序視爲不將頁存儲在後退緩存中的信號,但Safari會忽略此類處理程序。


解決方案

我只找到一個工作的解決方案,但它是一個有點不完善,哈克和醜陋。

您可以檢查onpageshow事件的持續屬性。它在初始頁面加載時設置爲false。當頁面從back-forward cache加載時,它被設置爲true

onpageshow事件與onload事件類似,只不過它在頁面首次加載時發生在onload事件之後。此外,每次加載頁面時都會發生onpageshow事件,而從緩存加載頁面時不會發生onload事件。

必須注意的:

的解決方案是相當不完善的頁面仍然是重裝之前短暫顯示。這意味着,你的頁面加載......然後 - 它被迫重新開始。畢竟,它不像它在頁面完全加載後觸發重新加載,但仍然是。

還有一個小問題:當然,解決方法很容易通過禁用javascript來繞過。

所以,用它在你自己的責任:

window.onpageshow = function(event) { 
    if (event.persisted) { 
     window.location.reload(); 
    } 
}; 

現金

+0

非常感謝@卡洛揚。我會在今天晚些時候嘗試解決方案並報告。並可能給你的賞金:-) – juanmirocks

+1

謝謝@ juanmirocks,我明白:-) –

+0

非常感謝你。你的回答非常清楚,非常豐富(爲你帶來賞金!)。 **非常不幸**,在嘗試提出的解決方案後,我仍然體驗到與Safari相同的以前的行爲。我測試了'http'和'https'。更多信息,事件'pageshow'總是將'persisted'屬性設置爲'false'。事實上,我根本不使用後退/前進按鈕。相反,我在具有普通頁面鏈接的頁面之間導航。所以我不知道...... ---真的很感激,如果你能想出其他假設:) – juanmirocks