需求
有三個頁面A、B、C,點擊A=>B,點擊B=>C,在C中添加內容,點擊確定返回到B,此時B頁面需重新加載新的內容。再次點擊B的返回按鈕,希望返回到A而不是C。
===== 2017/5/10 更新 ======
IOS 瀏覽器的詭異表現:history.go(-1)返回上一頁后,頁面內容並不會刷新。在C頁面添加的內容,返回到B時並沒有更新新的內容,必須手動刷新。
經過debug,發現在ios瀏覽器中,返回上一頁后,頁面的 JS 代碼並未執行。我們猜測可能是緩存引起的,於是使用 meta 禁止了緩存,但仍然沒有效果。於是進一步猜測可能是瀏覽器內部機制導致——ios為了提升瀏覽網頁的效率,可能給已瀏覽過的網頁添加一個類似快照的東西,當點擊返回按鈕后,直接調用快照展示給用戶,省去了執行JS這一步驟(純靜態文件依然被緩存)。
於是想到一個hack方法:
//C頁面
sessionStorage.setItem('isHistory', 'true');
// B頁面
if(navigator.userAgent.match( /(?:iPad|iPod|iPhone).*OS\s([\d_]+)/ )) {
var timer = setInterval(function(){
if(sessionStorage.getItem('isHistory') == 'true') {
sessionStorage.setItem('isHistory', 'false');
timer = null;
location.reload();
}
},30);
}
===== end =====
分析需求
顯然,此需求有兩個功能:
- 頁面中的返回上一頁功能
- C中添加內容,返回B后刷新頁面,同時保證B頁面返回功能的正常使用
解決方案
針對第一個問題,我們很容易想到history.back()
或者history.go(-1)
難點在第二個問題,最開始我是這樣解決的:loacation.href = document.referrer
,此時,B頁面內容正確顯示,但點擊返回按鈕卻到了C。
分析原因,原來是loacation.href
相當於重新加載了一次B頁面,那么當前B頁面的上一頁自然就是C了。
有沒有辦法使得B頁面不重新加載,但更新內容呢?
使用Ajax!!!瀏覽器加載頁面后,會緩存HTML,每次加載頁面都會執行一遍JS
1、C 頁面點擊確定后使用history.go(-1)
,返回到B頁面
2、在 B 頁面通過$.ajax()
獲取內容
var xhr = $.ajax({
type: 'GET',
url: '/api/xxx/xx',
timeout: 5000,
dataType: 'json',
beforeSend: function(XHR){
// todo
},
success: function(json){
//
},
error: function(){},
complete: function(xhr,status){}
})
3、重點,使用自執行函數渲染頁面
<script>
function B(){};
B.prototype.getData(){
var xhr = $.ajax({...})
};
B.prototype.renderPage(){
this.getDate();
// render...
};
!function(window){
var b = new B();
b.renderPage();
}(window)
</script>
這下應該成了吧。NO! C點擊確定后返回到B,B內容依然沒有更新。。。
這是為什么呢?
百度搜索無果,情急之下只有求救大神
大神說,可能是GET
請求發出后,由於URL沒有變化,瀏覽器可能會從緩存中讀取數據而導致內容更新失敗。
- 使用POST請求,強制從服務器獲取數據
- 仍然使用GET,改變當前頁面的
url
,方法是在url
末尾添加一段隨機字符串
兩種方法都能實現需求,這里再說說方法二:
var xhr = $.ajax({
type: 'GET',
url: '/api/xxx/xx',
timeout: 5000,
dataType: 'json',
data: {flag: new Date().getTime().toString(36)}, // 在GET方法內添加一個任意key,隨機字符串改變
beforeSend: function(XHR){
// todo
},
success: function(json){
//
},
error: function(){},
complete: function(xhr,status){}
})