一、浏览器历史API
浏览器历史就像一堆卡片,如下所示:
在HTML4中,我们已经可以使用window.history对象来控制历史记录的跳转,可以使用的方法包括:
HTML5引进了history.pushState()方法和history.replaceState()方法,它们允许你逐条地添加和修改历史记录条目。这些方法可以协同window.onpopstate
事件一起工作。
方法 | 描述 |
pushState() | 有三个参数:一个状态对象、一个标题(现在会被忽略),一个可选的URL地址 |
replaceState() | 操作类似于history.pushState(),不同之处在于replaceState()方法会修改当前历史记录条目而并非创建新的条目。 |
popstate事件 | 每当激活的历史记录发生变化时,都会触发popstate事件。 |
如果要做浏览器兼容,可以下载History.js解决。下面做个简单的demo:
<h1 id="number">1</h1> <a id="forward" href="?num=2">Go Forward</a>
var link = document.getElementById('forward'); var num = document.getElementById('number'); link.addEventListener('click', function(e){ e.preventDefault(); var myNum = parseInt(num.innerHTML, 10); num.innerHTML = ++myNum; history.pushState({count:myNum}, null, '?num='+myNum); document.title = 'Number'+myNum; });
点击按钮的时候,上面的URL在改变,但点击浏览器的后退按钮的时候,上面的内容是不变的。
接下来,我们给popstate加个监听器,监听数字。数字内容也就会随着改变了。
addEventListener('popstate', function(e){ if(e.state && e.state.count) { num.innerHTML = e.state.count; document.title = 'Number'+e.state.count; }else { num.innerHTML = 1; document.title = 1; } });
二、创建一个路由
PAJX就是pushState+Ajax。同时使用这两者,只需更新页面的一小部分和URL,页面不需要重新加载,这样就能极大加快访问速度。
建立一个单页程序的方法很多,最简单的就是使用一个路由。
var routes = []; //建立route对象,插入到数组routes中 function addRoute(route, callback, scope) { var routeObj = { route: route, callback: callback, scope, scope }; routes.push(routeObj); } //匹配符合要求的route,并执行回调函数 function handleRoute(path, noHistory) { var len = routes.length, scope; for(var i=0; i<len; i++) { if(path.match(routes[i].route)) { //如果给定了作用域就用给的作用域 if(routes[i].scope) { scope = routes[i].scope; }else { scope = window; } //如果是来自popstate事件,就不必再加入到栈中 if(!noHistory) { history.pushState({}, null, path); } routes[i].callback.apply(scope, [path]); return true; } } //没有route返回false return false; }
只需添加一个监听器就能让历史记录起作用。
window.addEventListener('popstate', function(e) { handleRoute(window.location.href, true); }); router = { handleRoute:handleRoute, addRoute:addRoute };
给页面上的a标签按钮添加事件
//拦截单击,简单的绑定页面上面的a标签的点击事件 document.addEventListener('click', function(e) { if(e.target.href) { if(router.handleRoute(e.target.href)) { e.preventDefault(); } } });
三、添加ajax请求
这里还做了点简单的缓存操作。点击后退按钮页面上的内容还能存在。
//缓存ajax的响应 var pageCache = {}; //格式化链接 function normalizeLink(path) { return path.match(/([a-z_]+\.html)/)[1]; } //执行ajax请求或使用缓存 function handlePage(path) { var href = normalizeLink(path); if(pageCache[href]) { document.querySelector('.content').innerHTML = pageCache[href]; } else { ajax.makeRequest(href.replace('.html', '_frag.html'), function(xhr) { document.querySelector('.content').innerHTML = xhr.responseText; pageCache[href] = xhr.responseText; }, this); } } router.addRoute(/[a-z_]+\.html/, handlePage);
代码是参照《HTML5触摸界面设计与开发》这本书的示例demo而写的。这本书的源码可以在这里获取到。
demo下载:
http://download.csdn.net/detail/loneleaf1/8730963