vue-router 源码实现前端路由的两种方式


Posted in Javascript onJuly 02, 2018

在学习 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.pushStatehistory.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;
 }
}

实现效果如下:

vue-router 源码实现前端路由的两种方式 

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;
 }
}

实现效果如下:

vue-router 源码实现前端路由的两种方式

最后

前端路由实现方式有两种,分别是:

  1. Hash 路由
  2. History 路由

原理都是修改 url 的同时不刷新页面,不向服务器发送请求,通过监听特殊的事件来更新页面。

以上实现全部源码参考这里。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS 去前后空格大全(IE9亲测)
Jul 15 Javascript
JS来动态的修改url实现对url的增删查改
Sep 05 Javascript
JavaScript日期时间与时间戳的转换函数分享
Jan 31 Javascript
js简单倒计时实现代码
Apr 30 Javascript
基于jQuery ligerUI实现分页样式
Sep 18 Javascript
Node.js的文件权限及读写flag详解
Oct 11 Javascript
canvas 绘制圆形时钟
Feb 22 Javascript
使用vue.js编写蓝色拼图小游戏
Mar 17 Javascript
使用watch监听路由变化和watch监听对象的实例
Feb 24 Javascript
Vue 中使用vue2-highcharts实现曲线数据展示的方法
Mar 05 Javascript
vue项目中jsonp跨域获取qq音乐首页推荐问题
May 30 Javascript
实例讲解v-if和v-show的区别
Jan 31 Javascript
React Native基础入门之调试React Native应用的一小步
Jul 02 #Javascript
vue-router 源码之实现一个简单的 vue-router
Jul 02 #Javascript
JavaScript设计模式之单例模式简单实例教程
Jul 02 #Javascript
JavaScript设计模式之建造者模式实例教程
Jul 02 #Javascript
JS实现的JSON序列化操作简单示例
Jul 02 #Javascript
JS内部事件机制之单线程原理
Jul 02 #Javascript
JS将网址url转化为JSON格式的方法
Jul 02 #Javascript
You might like
PHP优于Node.js的五大理由分享
2012/09/15 PHP
thinkphp框架下404页面设置 仅三步
2016/05/14 PHP
php实现登录tplink WR882N获取IP和重启的方法
2016/07/20 PHP
由JavaScript技术实现的web小游戏(不含网游)
2010/06/12 Javascript
jquery动态增加text元素以及删除文本内容实例代码
2013/07/01 Javascript
jquery配合css简单实现返回顶部效果
2013/09/30 Javascript
模拟用户点击弹出新页面不会被浏览器拦截
2014/04/08 Javascript
移动设备web开发首选框架:zeptojs介绍
2015/01/29 Javascript
javascript中callee与caller的区别分析
2015/04/20 Javascript
使用canvas实现仿新浪微博头像截取上传功能
2015/09/02 Javascript
jquery实现简单实用的弹出层效果代码
2015/10/15 Javascript
值得分享和收藏的Bootstrap学习教程
2016/05/12 Javascript
Javascript动画效果(4)
2016/10/11 Javascript
JavaScript实现网页头部进度条刷新
2017/04/16 Javascript
jQuery+PHP实现上传裁剪图片
2020/06/29 jQuery
利用js-cookie实现前端设置缓存数据定时失效
2019/06/18 Javascript
开源一个微信小程序仪表盘组件过程解析
2019/07/30 Javascript
jQuery实现消息弹出框效果
2019/12/10 jQuery
jQuery实现简易聊天框
2020/02/08 jQuery
[01:03:13]VG vs Pain 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
Python实现的字典值比较功能示例
2018/01/08 Python
对Xpath 获取子标签下所有文本的方法详解
2019/01/02 Python
在django view中给form传入参数的例子
2019/07/19 Python
django框架单表操作之增删改实例分析
2019/12/16 Python
Python字符串中删除特定字符的方法
2020/01/15 Python
python框架flask入门之路由及简单实现方法
2020/06/07 Python
解决Keras 自定义层时遇到版本的问题
2020/06/16 Python
在Python3.74+PyCharm2020.1 x64中安装使用Kivy的详细教程
2020/08/07 Python
英国第二大营养品供应商:Vitabiotics
2016/10/01 全球购物
幼儿园区域活动总结
2014/05/08 职场文书
注册资产评估专业求职信
2014/07/16 职场文书
2015秋学期开学寄语
2015/05/28 职场文书
2015暑假假期总结
2015/07/13 职场文书
2016年度员工工作表现评语
2015/12/02 职场文书
大学生安全教育心得体会
2016/01/15 职场文书
慰问信的写作格式及范文!
2019/06/24 职场文书