需求
有三个页面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).*OSs([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){}
})