因爲 IOS 系統的頁面緩存機制,常常會遇到在移動端返回到上一個頁面不刷新的狀況。css
好比今天在開發微信 H5 頁面的時候,在IOS微信內置瀏覽器中返回上一頁時,上一個頁面不會被刷新。 而一般在瀏覽器緩存機制中,在返回上一頁的操做中, html/css/js/接口 等動靜態資源不會從新請求,可是js會從新加載。但在IOS微信頁面中js也會保存上一頁面最後執行的狀態,不會從新執行js。 使用這種模式的緩存機制能夠加快渲染速度,可是部分數據須要常常展現和編輯的狀況下會致使不一樣步。好比‘詳情頁’跳轉到‘編輯頁’,編輯完後再返回到‘詳情頁’,若是‘詳情頁’數據展現未進行同步修改那確定是不能接受的。 在webview和5+的混合app模式中,也會遇到這種返回上一個頁面不刷新的問題html
瀏覽器前進/後退緩存前端
這裏提到一個概念,瀏覽器前進/後退緩存(Backward/Forward Cache, BF Cache),固然也有人叫 disk Cache。 BF Cache 是一種瀏覽器優化, HTML 標準並未指定其如何進行緩存,所以緩存行爲是各瀏覽器各自實現,因此不盡相同。 因爲不是 HTTP 緩存,因此經過頭文件緩存設置 no-cache 是無效的。固然也不能以 HTTP 緩存機制來理解 BF Cache。ios
設置瀏覽歷史當前記錄web
//監聽後退返回事件 --解決微信返回不刷新問題
pushHistory: function(){
window.addEventListener("popstate", function(e) {
self.location.reload();
}, false);
var state = {
title : "",
url : "#"
};
window.history.replaceState(state, "", "#");
},
/** * 頁面初始化調用pushHistory,監聽popstate事件和執行replaceState() * 當執行replaceState()時,不會觸發popstate事件,因此不會重複刷新 * 當在ios微信內置瀏覽器中執行瀏覽器前進後退操做時,觸發popstate事件,執行location.reload() * 可是在谷歌瀏覽器中執行瀏覽器前進後退操做時,不會觸發popstate事件!由於不在一個document中了 * 可是若是手動改變URL的哈希值,好比www.baidu.com# 改爲 www.baidu.com#1 會觸發popstate事件,執行location.reload() * 以上若是有一項不理解或不清晰,請往下看原理深究,你會找到答案 **/
複製代碼
前端路由實現(history)原理chrome
之前瀏覽器操做瀏覽器歷史記錄主要依據history對象。在它的 proto 繼承有 back、forward、go 等函數。 而 HTML5 後新增 popState 來控制瀏覽歷史記錄的 api。有能夠存儲當前歷史記錄點的 pushState、替換當前歷史記錄點的 replaceState、和監聽歷史記錄點的 onPopState。api
window.history.pushState(state, title, url)瀏覽器
window.history.replaceState(state, title, url)緩存
window.onpopstate事件bash
pushState 和replaceState 的第一個參數 stateObj,會與第三個參數對應的歷史條目綁定在一塊,當 popstate 事件觸發的時候,意味着有新的歷史記錄條目被激活,在 popstate 的事件對象裏面,有一個 state 屬性,會返回這個激活條目關聯的 stateObj 對象的拷貝。一個歷史記錄條目只有當它是被 pushState 建立的,或者用 replaceState 改過的,纔可能有關聯的 stateObj 對象,因此當某些非這2種條件的歷史記錄條目被激活的時候,可能拿到的 stateObj 就是 null。
禁止返回上一頁的一種方案
/**
* 向歷史記錄中手動添加一條記錄
* 用戶選擇返回的時候,每次都會消耗一個 history 實體,此時觸發 popstate 監聽事件,再手動添加一條history實體記錄
* 因此用戶不管點擊多少次都會永遠留在這個頁面了,固然頁面也不會刷新
**/
function pushHistory() {
window.history.pushState(null, null, "#");
window.addEventListener("popstate", function (e) {
console.log(e);
window.history.pushState(null, null, "#");
}, false);
}
複製代碼
URL 中的 # 就表示的是 URL 的哈希值
設置方法:
step1:設置一個錨點<a href="#print">定位到print位置</a>
step2:在頁面須要定位的內容加上id="print"。例如:<div id="print"></div> 或者 <a name="print"></a>
測試:step1設置的錨點,step2中id爲print的內容會滾動到頁面頂端(可觀察滾動條的距離)。同時,頁面的url末端中會出現 # print的哈希值。
複製代碼
HTTP請求不包含#
#號是用來指導瀏覽器動做的,對服務器端徹底無用。
在第一個#後面出現的任何字符,都會被瀏覽器解讀爲位置標識符。這意味着,這些字符都不會被髮送到服務器端。
訪問下面的網址: www.w3cschool.cn/#hello 瀏覽器實際發出的請求時這樣的:
改變#不觸發網頁重載
單單改變#後的內容,瀏覽器只會滾動到相應位置,不會從新加載網頁。
瀏覽器也不會從新向服務器請求頁面
改變#會改變瀏覽器的訪問歷史
每一次改變#後的部分,都會在瀏覽器的訪問歷史中增長一個記錄,使用"後退"按鈕,就能夠回到上一個位置。
window.location.hash讀取#值
window.location.hash這個屬性可讀可寫。讀取時,能夠用來判斷網頁狀態是否改變;寫入時,則會在不重載網頁的前提下,創造一條訪問歷史記錄。
onhashchange事件
這是一個HTML 5新增的事件,當#值發生變化時,就會觸發這個事件。IE8+、Firefox 3.6+、Chrome 5+、Safari 4.0+支持該事件。
// 它的使用方法有三種:
window.onhashchange = func;
<body onhashchange="func();">
window.addEventListener("hashchange", func, false);
複製代碼
Google抓取#的機制
默認狀況下,Google的網絡蜘蛛忽視URL的#部分。
可是,Google還規定,若是你但願Ajax生成的內容被瀏覽引擎讀取,那麼URL中可使用"#!",Google會自動將其後面的內容轉成查詢字符串_escaped_fragment_的值。
好比,Google發現新版twitter的URL:twitter.com/#!/username
就會自動抓取另外一個URL:twitter.com/?escaped_fragment=/username 經過這種機制,Google就能夠索引動態的Ajax內容。