就目前来看,前端的单页面开发占了很大一部分,一方面无刷新的切换加强了体验,而且浏览器记录依然存在,前进后退都没问题,在以前咱们通地址栏中的hash改变来触发onhashchange方法来实现单页面应用,可是#的形式老是使人不爽,幸亏h5新增了history.pushState与history.replaceState。javascript
1.介绍APIhtml
history.pushState(data, title [, url]):前端
往历史记录堆栈顶部添加一条记录; data会在onpopstate事件触发时做为参数传递过去,title为页面标题,当前全部浏览器都会 忽略此参数(咱们在本身实现的时候能够随便填写),url为页面地址,就是若是history.pushState({name:'home'},'home page' ,'home')则地址栏就成了/home,更神奇的是此时不会向后端发送请求,仅仅是url改变。vue
history.replaceState(data, title [, url]) :java
更改当前的历史记录,参数跟history.pushState(data, title [, url])一致,只不过不会像浏览器历史栈添加数据,而是替代以前的历史记录; node
history.state:用于存储以上方法的data数据,git
window.onpopstate:响应pushState或replaceState的调用;github
2.介绍实现单页面原理ajax
经过以上几个方法咱们彻底能够改变url而且监听到url的变化,好比url由localhost:8000改变成localhost:8000/home,此时咱们经过onpopstate监听到了这个变化,而且拿到data数据,假设拿到了name,此时假设有如下对应路由表,其实能够随便定义,express
let route = { home:{ name:'home', url:'./home.html', des:'home page' }, class:{ name:'class', url:'./class.html', des:'class page' } }
那咱们就知道此时home对应应该是./home.html,因而咱们利用ajax将./home.html加载过来,此时咱们拿到了home.html的全部信息,因而跟vue或者其余框架同样挂载到当前页面的一个元素上。
注意点:
咱们主动 利用history.pushState({name:'home'},'home page' ,'home')时候并不会触发onpopstate,就是说此时是没法知道url变更了,为了让页面顺利跳转又触发咱们提供的ajax,那么咱们就要修改一下history.pushState
var pushState = history.pushState; // 存储原生 replaceState history.pushState = function(state, param) { // 改写 replaceState var urlName = arguments[2]; var url = route[urlName].url; ajax(url) return pushState.apply(history, arguments); // 调用原生的 replaceState };
如上,咱们不只在使用 history.pushState时候,触发咱们本身定义的ajax函数,加载了页面,又调用了原生的方法,是不会影响原生历史记录和跳转等问题。
如今咱们知道咱们每次调用history.pushState都会触发ajax函数
<div id="app"></div> <script> function ajax(url){ //步骤一:建立异步对象 var ajax = new XMLHttpRequest(); //步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,能够带参数,动态的传递参数starName到服务端 ajax.open('get',url); //步骤三:发送请求 ajax.send(); //步骤四:注册事件 onreadystatechange 状态改变就会调用 ajax.onreadystatechange = function () { if (ajax.readyState==4 &&ajax.status==200) { //步骤五 若是可以进到这个判断 说明 数据 完美的回来了,而且请求的页面是存在的 //输入相应的内容 document.querySelector('#app').innerHTML = ajax.responseText } } } <script>
利用这个ajax就能够将别的页面的内容加载到本页面的#app这个元素上,实现了单页面跳转。
3.须要注意的地方和坑:
1.在尝试该方法前,须要其启动服务器代理html文件,即静态的html文件打开会报错
2.咱们在经过history.pushState改变url浏览器并不会跟处理普通url同样新发送请求,可是咱们在刷新的时候浏览器仍是会发送请求,即localhost:8000/home刷新浏览器就会请求这个接口,就会致使后台根本没有这个路由返回404,(这也是vue-route常常会出现刷新404问题的缘由)解决办法就是遇到404的都代理给index.html,我测试使用express来起服务的,有一个插件叫 connect-history-api-fallback,使用以后就不会出现这个问题。
若是有想要本身尝试的,这里附上咱们demo:https://github.com/jiangzhenfei/h5History,下载还只要执行node server.js便可,打开浏览器就能够尝试了。