现在基本都是单页面应用,现在单页面应用能够模拟多页面应用的效果,归功于其前端路由机制。现在前端路由有两种形式:
Hash模式
如: xxx.xx.com/#/hash, 这种方式可以实现刷新跳转,不需要后端进行配合,主要是得益于haschange事件,当锚点哈希改变时,就会调用haschange函数,
haschange模拟实现
(function(window) {
// 如果浏览器原生支持该事件,则退出
if ( "onhashchange" in window.document.body ) { return; }
var location = window.location,
oldURL = location.href,
oldHash = location.hash;
// 每隔100ms检测一下location.hash是否发生变化
setInterval(function() {
var newURL = location.href,
newHash = location.hash;
// 如果hash发生了变化,且绑定了处理函数...
if ( newHash != oldHash && typeof window.onhashchange === "function" ) {
// execute the handler
window.onhashchange({
type: "hashchange",
oldURL: oldURL,
newURL: newURL
});
oldURL = newURL;
oldHash = newHash;
}
}, 100);
})(window);
例子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
<li><a href="#/css">css</a></li>
<li><a href="#/js">js</a></li>
<li><a href="#/node">node</a></li>
</ul>
<div class="wrapper">
当前选择的是:<span></span>
</div>
</body>
<script>
window.onhashchange = function (e) {
console.log(e);
document.querySelector('.wrapper span').innerText = location.hash.split('/')[1]
}
</script>
</html>
H5模式
如:xxx.xx.com/hash 这种模式需要后端路由配合使用。HTML5的History API为浏览器的全局history对象增加的扩展方法。一般用来解决ajax请求无法通过回退按钮回到请求前状态的问题
在HTML4中,已经支持window.history对象来控制页面历史记录跳转,常用的方法包括:
- history.forward(); //在历史记录中前进一步
- history.back(); //在历史记录中后退一步
- history.go(n): //在历史记录中跳转n步骤,n=0为刷新本页,n=-1为后退一页。
在HTML5中,window.history对象得到了扩展,新增的API包括:
- history.pushState(data[,title][,url]);//向历史记录中追加一条记录
- history.replaceState(data[,title][,url]);//替换当前页在历史记录中的信息。
- history.state;//是一个属性,可以得到当前页的state信息。
- window.onpopstate;//是一个事件,在点击浏览器后退按钮或js调用forward()、back()、go()时触发。监听函数中可传入一个event对象,event.state即为通过pushState()或replaceState()方法传入的data参数。注意调用pushState和replaceState不会触发onpopstate事件
history.pushState({page: 1}, null, '?page=1');
history.pushState({page: 2}, null, '?page=2');
history.back(); //浏览器后退
window.addEventListener('popstate', function(e) {
//在popstate事件触发后,事件对象event保存了当前浏览器历史记录的状态.
//e.state保存了pushState添加的state的引用
console.log(e.state); //输出 {page: 1}
});