路由,简单来说就是用来跟后端服务器进行交互的一种方式,通过不同的路径,来请求不同的资源,请求不同的页面是路由的其中一种功能。后端有后端路由,根据路由返回特定的网页,代表者是传统的mvc模式,模板引擎+node。前端也有前端的路由,我们用三大框架做spa的时候,总是和路由离不开关系。
其中, “更新视图但不重新请求页面”是前端路由原理的核心之一。
目前实现前端路由的两种方法:
利用URL中的hash(“#”)
利用History interface在 HTML5中新增的方法
hash方法
#
后面的内容是网页位置标识符,一般是锚点<a name='xx'>
或id属性<div id='xx'>
。通过location.hash
可以取到该值,常见的返回顶部也可以利用href='#'
。- 改变#后面的内容不会引起页面重新刷新,但是会有历史记录,所以可以后退。
- 这对于ajax应用程序特别有用,可以用不同的#值,表示不同的访问状态,然后向用户给出可以访问某个状态的链接。(但是IE 6和IE 7不会有历史记录。
#
后面的内容不会提交到服务器。) - 对于a标签,平时有一个常规的操作:
想要在某个点击按钮变成a标签的那个cursor:pointer
(手指),一般就用a
标签包住文字,<a href="#">按钮</a>
但是这样子是会有历史记录,所以我们应该改成<a href="javascript:void 0">按钮</a
>
使用hash方法实现vue-router:
class Routers {
constructor () {
this.routes = {}; // 存放路由path及callback
this.currentUrl = '';
this.refresh = this.refresh.bind(this);
// 监听路由change调用相对应的路由回调
window.addEventListener('load', this.refresh, false);
window.addEventListener('hashchange', this.refresh, false);
}
route(path, callback){
this.routes[path] = callback;
}
push() {
this.currentUrl = location.hash.slice(1) || '/';
this.routes[this.currentUrl] && this.routes[this.currentUrl]()
}
}
简版的hash router 已经实现了, 我们可以这样使用
window.VueRouter = new Routers();
VueRouter.route('/', ()=> console.log('page1'))
VueRouter.route('/detail', ()=> console.log('page2'))
history方法
- history 对象
- history.pushState()方法用于在历史中添加一条记录。
- history.replaceState()方法用来修改 History 对象的当前记录,其他都与pushState()方法一模一样。
- history.popState 每当同一个文档的浏览历史(即history对象)出现变化时,就会触发popstate事件。
使用history方法实现vue-router:
class Routers {
contructor () {
this.routes = {};
this.listerPopState()
}
init(path) {
history.replaceState({path: path}, null, path);
this.routes[path] && this.routes[path]();
}
route(path, callback){
this.routes[path] = callback;
}
push(path) {
history.pushState({path: path}, null, path);
this.routes[path] && this.routes[path]();
}
listerPopState () {
window.addEventListener('popstate' , e => {
const path = e.state && e.state.path;
this.routers[path] && this.routers[path]()
})
}
}
简版的history router 已经实现了, 我们可以这样使用
window.VueRouter = new Routers();
VueRouter.route('/', ()=> console.log('page1'))
VueRouter.route('/detail', ()=> console.log('page2'))
// 跳转
VueRouter.push('/detail') // page2
如果你嫌哈希路由有#
难看可以用history路由。不过history路由有一个问题,我们知道pushState和replaceState只是对url栏进行改变,不会触发页面刷新,只是导致history对象发生变化,另外也==不能跨域==。既然不会触发页面更新,那么也不会发送http请求,就有了一个问题:如果直接输入url,后端又没有对应的url处理的话,那肯定是404,而哈希路由则可以直接输入 url直接定位到某个视图。
参考: