因为 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内容。