監控頁面后退前進,瀏覽器文檔加載事件之pageshow、pagehide


首先說說為什么會學習這個pageshow的起因吧,項目中一個表單頁面,需得填寫驗證碼,填寫驗證碼后提交,由於使用的form直接提交,沒有使用AJAX,所以,在出現驗證碼填寫錯誤的時候,就會跳轉到錯誤提示頁,3秒倒計時后使用history.back(-1)的方式返回上一頁,這也就出現了一個問題,使用history.back(-1)進行后退之后,圖形驗證碼已過期,但是卻沒有刷新,這樣就導致用戶重復多次填寫驗證碼,影響用戶體驗;

發現了問題,首先分析一下唄:

*瀏覽器前進、后退使用機制

*如何在前進、后退后執行js

一. 問題一:瀏覽器前進、后退使用機制

用戶點擊瀏覽器工具欄中的后退按鈕,或者移動設備上的返回鍵時,或者JS執行history.go(-1);時,瀏覽器會在當前窗口“打開”歷史紀錄中的前一個頁面。不同的瀏覽器在“打開”前一個頁面的表現上並不統一,這和瀏覽器的實現以及頁面本身的設置都有關系。在瀏覽器中,“后退到前一個頁面”意味着:前一個頁面的html/js/css等靜態資源的請求(甚至是ajax動態接口請求)根本不會重新發送,直接使用緩存的響應,而不管這些靜態資源響應的緩存策略是否被設置了禁用狀態。
各個瀏覽器測試demo:先點擊按鈕使其變色,然后調整至百度,再后退回來查看:

function dispLog(msg) {
  var d = new Date();
  $("<li />").text(d.toISOString().substr(14, 9) + " " + msg)
  .appendTo("#dvDisp");
}

window.addEventListener('load', function(event) {
	dispLog("Load Event  ");
})
//引入了jq監聽ready事件做比較
$(window).ready(function () {
    dispLog("Ready Event");
 });
$("#btnSetColor").click(function () {
    $("#btnSetColor").css("background", "red");
})
window.addEventListener('pageshow', function(event) {
    dispLog("PageShow Event  " + event.persisted);
    //使用event.persisted判斷頁面是否使用bfcache,值為true或false;  注:如果使用jq綁定事件,需使用event.originalEvent.persisted;
})
window.addEventListener('pagehide', function(event) {
    dispLog("Load Event  " + event.persisted);
})
            

線上測試地址: pageshow
移動端測試demo:

本人的測試結果:

1.PC端瀏覽器

瀏覽器 首次進入頁面 點擊按鈕,再跳轉至百度,再后退
chrome 58.0.3029.9 執行ready→load→pageshow 重新執行ready→load→pageshow 按鈕顏色消失 頁面相當於重新刷新了
IE789 執行ready→load 重新執行ready→load 按鈕顏色消失 頁面相當於重新刷新了 pageshow不兼容IE10-
firefox 53.0.2 執行ready→load→pageshow 重新執行ready→load→pageshow 按鈕顏色消失 頁面相當於重新刷新了
QQBrowser 9.6 執行ready→load→pageshow 重新執行ready→load→pageshow 按鈕顏色消失 頁面相當於重新刷新了
360Browser 8.1.1.254 執行ready→load→pageshow 重新執行ready→load→pageshow 按鈕顏色消失 頁面相當於重新刷新了
Safari 5.1.7(沒mac,用的很早版本的windowsafari) 執行ready→load→pageshow 新增→pagehide→pageshow 按鈕顏色紅色 引用了緩存(event.persisted == true)

safari

PC端總結:現代的PC瀏覽器后退后基本都是重新執行load,對頁面重新進行一次加載,所以不會有上面的驗證碼不刷新的問題,由於窮屌沒有mac電腦,只下載了很久之前的safari瀏覽器,測試結果只做參考;

2.移動端瀏覽器 (安卓端),測試機型小米5S,iphone4s

瀏覽器 首次進入頁面 點擊按鈕,再跳轉至百度,再后退
UCBrowser 執行ready→load→pageshow 新增→pagehide→pageshow 按鈕顏色紅色 引用了緩存(event.persisted == true)
QQBrowser 執行ready→load→pageshow 新增→pagehide→pageshow 按鈕顏色紅色 引用了緩存(event.persisted == true)
QQ內置瀏覽器 執行ready→load→pageshow 重新執行ready→load→pageshow 按鈕顏色消失 頁面相當於重新刷新了
360Browser 執行ready→load→pageshow 無觸發事件,按鈕顏色紅色 引用了緩存(event.persisted == true)
chorme 執行ready→load→pageshow 重新執行ready→load→pageshow 按鈕顏色消失 頁面相當於重新刷新了
微信內置 執行ready→load→pageshow 重新執行ready→load→pageshow 按鈕顏色消失 頁面相當於重新刷新了
小米自帶 執行ready→load→pageshow 無觸發事件,按鈕顏色紅色 引用了緩存(event.persisted == true)
safari 執行ready→load→pageshow 新增→pagehide→pageshow 按鈕顏色紅色 引用了緩存(event.persisted == true)

效果圖:選了三種類型各一個

刷新頁面類型 不刷新不執行類型
chrome測試頁面效果
不刷新執行事件類型(理想型)
這就很頭疼了,三種不同的情況,對於chrome和UC類型的情況,對於我的回退驗證碼刷新問題,很容易處理,最麻煩的360類型的,但是。。。發現了更蛋疼的情況了:
后退不reload,不執行pageshow的瀏覽器在公司的一個項目中,居然能實現后退刷新。。。。 同一段測試代碼,發到項目服務器上,是可以后退刷新,
但是,在我自己的虛擬主機中卻不行,南蝶?是因為請求頭部設置嗎??? 先挖個坑在這,等我去好好了解一下PHP 和 http請求 再回來戰!

二、如何在前進、后退后執行js

百度、google類似問題,最多的解決方法:pageshow;

Firefox和Opera有一個新特性,名叫“往返緩存”(back-forward cache,或bfcache),可以在用戶使用瀏覽器的“后退”和“前進”按鈕時加快頁面的轉換速度。
這個緩存中不僅保存着頁面數據,還保存了DOM和JavaScript的狀態;實際上是將整個頁面都保存在了內存里。
如果頁面位於bfcache中,那么再次打開該頁面就不會觸發load事件。
盡管由於內存中保存了整個頁面的狀態,不觸發load事件也不應該會導致什么問題,但為了更形象地說明bfcache的行為,Firefox還是提供了一些新事件。
第一個事件就是pageshow,這個事件在頁面顯示時觸發,無論頁面是否來自bfcache。在重新加載頁面中,pageshow會在load事件觸發后觸發;
而對於bfcache中的頁面,pageshow會在頁面狀態完全恢復的那一刻觸發。另外要注意的是,雖然這個事件的目標是document,但必須將其事件處理程序添加到window。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM