单页面应用中,路由由前端控制,前端实现路由主要有两种方式:
- 一是HTML5推出的history API,由pushState()记录操作历史,监听popstate事件来进行视图切换;
- 二是使用hash值,通过监听hashchange事件来进行视图切换
以下是一个路由示例:
<div id="route">
<a href="#/page1">page1</a>
<a href="#/page2">page2</a>
<a href="#/page3">page3</a>
</div>
<div id="content"></div>
var util = {
history: !!window.history && window.history.pushState,
hashchange: 'onhashchange' in window
}
window.onload = function () {
var router = new Router();
// 路由配置
router.when('/page1', {
template: '<h1>page1</h1>'
}).when('/page2', {
template: '<h1>page2</h1>'
}).when('/page3', {
template: '<h1>page3</h1>'
}).otherwise('/page1')
router.fireUrlChange();
if(util.history) {
// 页面地址改变,更新页面
$(window).on('popstate', function () {
router.fireUrlChange();
})
}
if(util.hashchange) {
// hash值改变时更新页面
$(window).on('hashchange', function () {
router.fireUrlChange();
});
}
}
function Router() {
this.routers = {};
}
Router.prototype = {
constructor: Router,
/**
* 添加路由
* @param path
* @param route
* @returns {Router}
*/
when: function (path, route) {
this.routers[path] = route;
return this;
},
/**
* 首次加载路由
* @param url
*/
otherwise: function (url) {
this.newUrl = url;
},
/**
* 路由改变时触发
*/
fireUrlChange: function () {
// 首次加载otherwise路由
if(!location.hash) {
if(util.history) {
history.pushState(null, '', location.href+'#'+this.newUrl);
}
if(util.hashchange) {
location.hash = this.newUrl;
}
}
this.newUrl = location.hash.substring(1);
// 路由没有变化
if(this.newUrl === this.lastUrl) {
return;
}
// 路由发生变化
this.lastUrl = this.newUrl;
//更新页面
var $content = $('#content');
$content.html(this.routers[this.newUrl].template);
}
}