实现单页应用开发,1.要做到页面无刷新 2.通过路由进行页面切换。
对于第一点我们使用ajax加载数据。第二点我们可以使用html5 history API中的history.pushState和history.replaceState实现.
以下是history相关api的使用:
history.pushState(),history.replaceState()
history.pushState方法接受三个参数,依次为:
state | 一个与指定网址相关的状态对象,popstate事件触发时,该对象会传入回调函数。如果不需要这个对象,此处可以填null |
title | 新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填nul |
url | 新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。 |
注意,pushState方法不会触发页面刷新。如果哟设置了一个非同域的网址,则会报错
假定当前网址是best-html5.com/a.html,我们使用pushState方法在浏览记录(history对象)中添加一个新记录。
var stateObj = { title: "page2", url: "page2.html" }; history.pushState(stateObj, "page 2", "page2.html");
添加上面这个新记录后,浏览器地址栏立刻显示best-html5.com/page2.html,但并不会跳转到page2.html,甚至也不会检查page2.html是否存在,它只是成为浏览历史中的最新记录。
history.replaceState方法的参数与pushState方法一模一样,区别是它修改浏览历史中当前页面的值
history.state属性
history.state属性保存当前页面的state对象。
history.pushState({page: 1}, "title 1", "?page=1"); history.state // { page: 1 }
popstate事件
每当同一个文档的浏览历史(即history对象)出现变化时,就会触发popstate事件。需要注意的是,仅仅调用pushState方法或replaceState方法 ,并不会触发该事件,只有用户点击浏览器倒退按钮和前进按钮,或者使用JavaScript调用back、forward、go方法时才会触发。另外,该事件只针对同一个文档,如果浏览历史的切换,导致加载不同的文档,该事件也不会触发。
使用的时候,可以为popstate事件指定回调函数。这个回调函数的参数是一个event事件对象,它的state属性指向pushState和replaceState方法为当前url所提供的状态对象(即这两个方法的第一个参数)。
window.onpopstate = function(event) { console.log("state: " + JSON.stringify(event.state)); }; // 或者 window.addEventListener('popstate', function(event) { console.log("state: " + JSON.stringify(event.state)); });
上面代码中的event.state,就是通过pushState和replaceState方法,为当前url绑定的state对象。
这个state对象也可以直接通过history对象读取。
var currentState = history.state;
另外,需要注意的是,当页面第一次加载的时候,在onload事件发生后,Chrome和Safari浏览器(Webkit核心)会触发popstate事件,而Firefox和IE浏览器不会
什么是PJAX
PJAX的基本思路是,用户点击一个链接,通过ajax更新页面变化的部分,然后使用HTML5的pushState修改浏览器的URL地址,这样有效地避免了整个页面的重新加载。如果浏览器不支持history的两个新API或者JS被禁用了,那这个链接就只能跳转并重新刷新整个页面了。和传统的ajax设计稍微不同,ajax通常是从后台获取JSON数据,然后由前端解析渲染,而PJAX请求的是一个在服务器上生成好的HTML碎片.
demo:
var Unit = { //判断浏览器是否支持history api support : { history : function(){ if (!!(window.history && history.pushState)){ return true; } else { return false; } } } } $(document).on("click", "a[data-pjax]", function(evt){ evt.preventDefault(); var uri=$(this).attr('href'); var _html=ajax_Load(uri); var newTitle = $(this).attr('data-title'); if(Unit.support.history()){ var state=({ url: uri, title: newTitle }); window.history.pushState(state, newTitle, uri); }else{ window.location.href="#!"+~fakeURI; } return false; }); function ajax_Load(uri){ $.ajax({ url: uri, }).done(function(data) { $("#main").html(data); }); } window.addEventListener('popstate', function(evt){ var state = evt.state; ajax_Load(state.url); }, false);
线上库: jquery-pjax.js