现象

详情页跳转到编辑页,编辑完后再返回到详情页,页面从缓存中取的数据,导致详情页数据出错。

https://img-blog.csdnimg.cn/20210318153240646.png

产生原因

浏览器前进/后退缓存

这里提到一个概念,浏览器前进/后退缓存(Backward/Forward Cache, BF Cache),当然也有人叫 disk Cache。 BF Cache 是一种浏览器优化, HTML 标准并未指定其如何进行缓存,因此缓存行为是各浏览器各自实现,所以不尽相同。 由于不是 HTTP 缓存,所以通过头文件缓存设置 no-cache 是无效的。当然也不能以 HTTP 缓存机制来理解 BF Cache。

深入理解浏览器的缓存机制

解决思路

一、添加meta标签设置不使用缓存

<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" />

二、添加刷新操作

  1. 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)
    
  2. 设置浏览历史当前记录

    /** 
     * 监听后退返回事件 --解决微信返回不刷新问题
     * 页面初始化调用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);
}