前端实现路由有两种方式,如下
History Api
自从H5开始,js的history就引入了<strong>history.pushState</strong>和<strong>history.replaceState</strong>两个方法,这两个允许添加和修改history实体,并可以和<strong>window.onpoState</strong>事件一起运作。
history.pushState(state,title,url)
history.replaceState(state,title,url)
它们基本相同,唯一不同的就是:pushStage 增加一条新的历史记录,而replaceState 替换当前的历史记录
state:state对象是一个JavaScript对象,它关系到由pushState()方法创建出来的新的history实体
title: 现在并无太大的意义
url:用来传递给新history实体的url,浏览器并不会真正的去加载这个url,但在用户重启浏览器时,有可能会加载这个url,url可以是绝对地址(必须是同意域名)或是相对地址(拼接在url后面)
下面看实例(注意地址栏url的变化):
<!DOCTYPE HTML>
<!-- this starts off as http://example.com/line?x=5 -->
<html>
<title>Line Game - 5</title>
<p>You are at coordinate <span id="coord">5</span> on the line.</p>
<p>
<a href="?x=6" onclick="go(1); return false;">Advance to 6</a> or
<a href="?x=4" onclick="go(-1); return false;">retreat to 4</a>?
</p>
<script>
var currentPage = 5; // prefilled by server!!!!
function go(d) {
setupPage(currentPage + d);
history.pushState(currentPage, null, '?x=' + currentPage);
}
onpopstate = function(event) {
setupPage(event.state);
}
function setupPage(page) {
currentPage = page;
document.title = 'Line Game - ' + currentPage;
document.getElementById('coord').textContent = currentPage;
document.links[0].href = '?x=' + (currentPage+1);
document.links[0].textContent = 'Advance to ' + (currentPage+1);
document.links[1].href = '?x=' + (currentPage-1);
document.links[1].textContent = 'retreat to ' + (currentPage-1);
}
</script>
<body>
</body >
</html>
hash
在一些网站中,我们经常会看到一些url带#,如标题之间切换、回到顶部等,在这里我们称为<strong>锚点</strong>,而在路由中,我们称为<strong>hash</strong>,并监听<strong>onhashchange</strong>事件。hash经常应用于大型框架路由中。
运行如下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="keywords" content="javascript" />
<meta name="description" content="geg" />
<title>演示:Javascript实现前端简单路由</title>
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
<style>
.text-right li{padding: 10px}
#result{height: 200px; line-height: 200px; font-size: 2rem; text-align: center; color:#fff;}
</style>
</head>
<body>
<div class="container">
<header>
<div class="row">
<div class="col-md-3 col-xs-12"><h1 class="logo"><a href="http://www.helloweba.com" title="返回helloweba首页">helloweba</a></h1></div>
<div class="col-md-9 text-right"></div>
</div>
</header>
<div class="row main" style="min-height:500px">
<div class="col-md-12">
<h2 class="top_title"><span class="glyphicon glyphicon-menu-left" aria-hidden="true"></span><a href="http://www.helloweba.com/view-blog-385.html">Javascript实现前端简单路由</a></h2>
<div class="row" style="margin-top:30px">
<div class="col-md-3">
<ul class="text-right">
<li><a href="#/">首页</a></li>
<li><a href="#/product">产品</a></li>
<li><a href="#/server">服务</a></li>
</ul>
</div>
<div class="col-md-7">
<div id="result"></div>
</div>
</div>
</div>
</div>
<footer>
<p>Powered by helloweba.com 允许转载、修改和使用本站的DEMO,但请注明出处:<a href="http://www.helloweba.com">www.helloweba.com</a></p>
</footer>
</div>
<script type="text/javascript">
function Router(){
this.routes = {};
this.curUrl = '';
this.route = function(path, callback){
this.routes[path] = callback || function(){};
};
this.refresh = function(){
this.curUrl = location.hash.slice(1) || '/';
this.routes[this.curUrl]();
};
this.init = function(){
window.addEventListener('load', this.refresh.bind(this), false);
window.addEventListener('hashchange', this.refresh.bind(this), false);
}
}
var R = new Router();
R.init();
var res = document.getElementById('result');
R.route('/', function() {
res.style.background = 'blue';
res.innerHTML = '这是首页';
});
R.route('/product', function() {
res.style.background = 'orange';
res.innerHTML = '这是产品页';
});
R.route('/server', function() {
res.style.background = 'black';
res.innerHTML = '这是服务页';
});
</script>
</body>
</html>
R::init()注册了监听事件(页面加载结束和hash变化)
R::router 存储路由更新时的回调到回调数组routes中,回调函数将负责对页面的更新。
refresh 执行当前url对应的回调函数,更新页面。
以上只是对路由的简单操作,实际中可以对hash加上正则的限制,同时增加ajax异步请求