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="#/">home</a> <a href="#/book">book</a> <a href="#/movie">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);" data-href="/">home</a> <a href="javascript:void(0);" data-href="/book">book</a> <a href="javascript:void(0);" data-href="/movie">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 的同时不刷新页面,不向服务器发送请求,通过监听特殊的事件来更新页面。
以上实现全部源码参考 这里。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Python函数式编程map()、reduce()
一、map() 格式:map(func, *iterables) map函数接受两个参数,第一个是要执行的函数,第二个是可迭代对象,可迭代对象可以传入多个参数。 map()函数是将func作用于iterables中的每一个元素,并用一个列表给出返回值。如果func为None,作用同zip()。 传入一个可迭对象 def func(x): return x*x lists = [1, 2, 3, 4] l = list(map(func, lists)) print(l) 结果:[1, 4, 9, 16] 传入两个可迭对象 def func(x, y): return x+y lists = [1, 2, 3, 4] lists2 = [1, 2, 3, 4] l = list(map(func, lists, lists2)) print(l) 结果:[2, 4, 6, 8] 二、reduce() 格式:reduce(function, sequence, initial=None) reduce函数接受三个参数,第一个是要执行的函数,第二个是序列,第三个是默认值。第一个函数必须有两个...
- 下一篇
JavaScript事件机制——记一次认真准备的技术分享
先问几个问题,你是否能快速闪过答案? 自下而上(冒泡)事件怎么写,自上而下(捕获)又是怎么写? 捕获型和冒泡型同时存在,谁生效? jquery的on或bind是冒泡,还是捕获? 冒泡能够阻止,那捕获能够阻止吗? stopPropagation 和 stopImmediatePropagation的区别 Event.bubbles,Event.eventPhase Event.cancelable,Event.cancelBubble,event.defaultPrevented 常用技巧 js事件的捕获和冒泡图 举个例子: 点击s2,s1分别会打印什么? <div id="s1">s1 <div id="s2">s2</div> </div> <script> s1.addEventListener("click",function(e){ console.log("s1 冒泡事件"); },false); s2.addEventListener("click",function(e){ console.log("s2 冒泡事...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果