vue-router 源码实现前端路由的两种方式
在学习 vue-router 的代码之前,先来简单了解一下前端路由。
前端路由主要有两种实现方法:
- hash 路由
- history 路由
先来看看这两种方法的实现原理。
接着我们将用它们来简单实现一个自己的前端路由。
前端路由
hash 路由
url 的 hash
是以 #
开头,原本是用来作为锚点,从而定位到页面的特定区域。当 hash
改变时,页面不会因此刷新,浏览器也不会向服务器发送请求。
http://www.xxx.com/#/home
同时, hash
改变时,并会触发相应的 hashchange
事件。所以,hash 很适合被用来做前端路由。当 hash 路由发生了跳转,便会触发 hashchange 回调,回调里可以实现页面更新的操作,从而达到跳转页面的效果。
window.addeventlistener('hashchange', function () { console.log('render'); });
history 路由
html5 规范中提供了 history.pushstate
和 history.replacestate
来进行路由控制。通过这两个方法,可以实现改变 url 且不向服务器发送请求。同时不会像 hash
有一个 #
,更加的美观。但是 history 路由需要服务器的支持,并且需将所有的路由重定向到根页面。
history 路由的改变不会去触发某个事件,所以我们需要去考虑如何触发路由更新后的回调。
有以下两种方式会改变 url:
- 调用 history.pushstate 或 history.replacestate;
- 点击浏览器的前进与后退。
第一个方式可以封装一个方法,在调用 pushstate(replacestate)后再调用回调。
function push (url) { window.history.pushstate({}, null, url); handlehref(); } function handlehref () { console.log('render'); }
第二个方式,浏览器的前进与后退会触发 popstate
事件。
window.addeventlistener('popstate', handlehref);
路由实现
我们通过 <a>
标签来进行切换路由,通过一个 <div>
标签来装载各路由对应的页面内容。
参考 vue-router 的调用,我们会这么地调用一个 router
,将路由与对应组件作为参数传入:
const router = new router([ { path: '/', component: 'home' }, { path: '/book', component: 'book' }, { path: '/movie', component: 'movie' } ]);
数组里是各路由对应的要显示的内容,接下来就来开始实现这个 router
。
hash 路由实现
hash 路由 <a>
标签都需要带上 #
:
<div> <a href="#/" rel="external nofollow" >home</a> <a href="#/book" rel="external nofollow" >book</a> <a href="#/movie" rel="external nofollow" >movie</a> <div id="content"></div> </div>
router
的代码实现如下:
class router { constructor (options) { this.routes = {}; this.init(); // 遍历,绑定视图更新 options.foreach(item => { this.route(item.path, () => { document.getelementbyid('content').innerhtml = item.component; }); }); } // 绑定监听事件 init () { window.addeventlistener('load', this.updateview.bind(this), false); window.addeventlistener('hashchange', this.updateview.bind(this), false); } // 更新试图 updateview () { const currenturl = window.location.hash.slice(1) || '/'; this.routes[currenturl] && this.routes[currenturl](); } // 将路由与回调函数关联 route (path, cb) { this.routes[path] = cb; } }
实现效果如下:
history 路由实现
history 路由需要服务器的支持,可以点击 的代码参考。
<div> <a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" data-href="/" rel="external nofollow" >home</a> <a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" data-href="/book" rel="external nofollow" >book</a> <a href="javascript:void(0);" rel="external nofollow" rel="external nofollow" rel="external nofollow" data-href="/movie" rel="external nofollow" >movie</a> <div id="content"></div> </div>
router
的代码实现如下:
class router { constructor (options) { this.routes = {}; this.init(); this.bindevent(); // 遍历,绑定视图更新 options.foreach(item => { this.route(item.path, () => { document.getelementbyid('content').innerhtml = item.component; }); }); } // 绑定点击事件 bindevent () { const _this = this; const links = document.getelementsbytagname('a'); [].foreach.call(links, link => { link.addeventlistener('click', function () { const url = this.getattribute('data-href'); _this.push(url); }); }); } // 绑定监听事件 init () { window.addeventlistener('load', this.updateview.bind(this), false); window.addeventlistener('popstate', this.updateview.bind(this), false); } push (url) { window.history.pushstate({}, null, url); this.updateview(); } // 更新试图 updateview () { const currenturl = window.location.pathname || '/'; this.routes[currenturl] && this.routes[currenturl](); } // 将路由与回调函数关联 route (path, cb) { this.routes[path] = cb; } }
实现效果如下:
最后
前端路由实现方式有两种,分别是:
- hash 路由
- history 路由
原理都是修改 url 的同时不刷新页面,不向服务器发送请求,通过监听特殊的事件来更新页面。
以上实现全部源码参考。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 鱼干怎么做好吃,吃多会不会有危害
下一篇: 君心谣