详情页跳转到编辑页,编辑完后再返回到详情页,页面从缓存中取的数据,导致详情页数据出错。
浏览器前进/后退缓存
这里提到一个概念,浏览器前进/后退缓存(Backward/Forward Cache, BF Cache),当然也有人叫 disk Cache。 BF Cache 是一种浏览器优化, HTML 标准并未指定其如何进行缓存,因此缓存行为是各浏览器各自实现,所以不尽相同。 由于不是 HTTP 缓存,所以通过头文件缓存设置 no-cache 是无效的。当然也不能以 HTTP 缓存机制来理解 BF Cache。
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
强缓存
强缓存根据请求头的Expires
和Cache-Control
判断是否命中强缓存,命中强缓存的资源直接从本地加载,不会发起任何网络请求。
Cache-Control
的值有很多:
Cache-Control: max-age=<seconds>
Cache-Control: max-stale[=<seconds>]
Cache-Control: min-fresh=<seconds>
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: only-if-cached
常用的有max-age
,no-cache
和no-store
。
max-age
是资源从响应开始计时的最大新鲜时间,一般响应中还会出现age
标明这个资源当前的新鲜程度。
no-cache
会让浏览器缓存这个文件到本地但是不用,Network中disable-cache
勾中的话就会在请求时带上这个haader,会在下一次新鲜度验证通过后使用这个缓存。
no-store
会完全放弃缓存这个文件。
服务器响应时的Cache-Control
略有不同,其中有两个需要注意下:
public
表明这个请求可以被任何对象缓存,代理/CDN等中间商。private
表明这个请求只能被终端缓存,不允许代理或者CDN等中间商缓存。Expires
是一个具体的日期,到了那个日期就会让这个缓存失活,优先级较低,存在max-age
的情况下会被忽略,和本地时间绑定,修改本地时间可以绕过。
另外,如果你的服务器的返回内容中不存在Expires
,Cache-Control: max-age
,或 Cache-Control:s-maxage
但是存在Last-Modified
时,那么浏览器默认会采用一个启发式的算法,即启发式缓存。通常会取响应头的Date_value - Last-Modified_value
值的10%作为缓存时间,之后浏览器仍然会按强缓存来对待这个资源一段时间,如果你不想要缓存的话务必确保有no-cache
或no-store
在响应头中。
pageshow
window.onpageshow = (event) => {
//页面是从缓存中获取的数据||是通过浏览器后退来到该页面
if (event.persisted || window.performance && window.performance.navigation.type == 2) {
window.location.reload();
}
}
window.addEventListener('pageshow', (event) => {
//页面是从缓存中获取的数据||是通过浏览器后退来到该页面
if (event.persisted || window.performance && window.performance.navigation.type == 2) {
window.location.reload();
}
}, false)
event.persisted 从缓存获取数据时为true,否则为false
window.performance
navigation
字段统计的是一些网页导航相关的数据:
redirectCount
重定向的数量(只读),但是这个接口有同源策略限制,即仅能检测同源的重定向;
type
一个无符号短整型。分别对应枚举值:
设置浏览历史当前记录
/**
* 监听后退返回事件 --解决微信返回不刷新问题
* 页面初始化调用pushHistory,监听popstate事件和执行replaceState()
* 当执行replaceState()时,不会触发popstate事件,所以不会重复刷新
* 当在ios微信内置浏览器中执行浏览器前进后退操作时,触发popstate事件,执行location.reload()
* 但是在谷歌浏览器中执行浏览器前进后退操作时,不会触发popstate事件!因为不在一个document中了
* 但是如果手动改变URL的哈希值,比如www.baidu.com# 改成 www.baidu.com#1 会触发popstate事件,执行location.reload()
*/
pushHistory: function(){
window.addEventListener("popstate", function(e) {
self.location.reload();
}, false);
var state = {
title : "",
url : "#"
};
window.history.replaceState(state, "", "#");
},
/**
* 禁止返回上一页
* 向历史记录中手动添加一条记录
* 用户选择返回的时候,每次都会消耗一个 history 实体,此时触发 popstate 监听事件,再手动添加一条history实体记录
* 所以用户无论点击多少次都会永远留在这个页面了,当然页面也不会刷新
*/
function pushHistory() {
window.history.pushState(null, null, "#");
window.addEventListener("popstate", function (e) {
console.log(e);
window.history.pushState(null, null, "#");
}, false);
}