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 相关文章推荐
JavaScript实用技巧(一)
Aug 16 Javascript
JS解析json数据并将json字符串转化为数组的实现方法
Dec 25 Javascript
JS 退出系统并跳转到登录界面的实现代码
Jun 29 Javascript
解析javascript系统错误:-1072896658的解决办法
Jul 08 Javascript
javascript实现div浮动在网页最顶上并带关闭按钮效果实例
Aug 13 Javascript
js全屏显示显示代码的三种方法
Nov 11 Javascript
javascript计算星座属相(十二生肖属相)示例代码
Jan 09 Javascript
jQuery实现可拖拽的许愿墙效果【附demo源码下载】
Sep 14 Javascript
jquery结合html实现中英文页面切换
Nov 29 Javascript
layui表格实现代码
May 20 Javascript
详解JavaScript中的六种错误类型
Sep 21 Javascript
vue2.0.js的多级联动选择器实现方法
Feb 09 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
2019年漫画销量排行榜:鬼灭登顶 海贼单卷制霸 尾田盛赞鬼灭
2020/03/08 日漫
在IIS上安装PHP4.0正式版
2006/10/09 PHP
制作安全性高的PHP网站的几个实用要点
2014/12/30 PHP
十大使用PHP框架的理由
2015/09/26 PHP
PHP函数超时处理方法
2016/02/14 PHP
php实现将数据做成json的格式给前端使用
2018/08/21 PHP
PHP htmlspecialchars()函数用法与实例讲解
2019/03/08 PHP
Ctrl+Enter提交内容信息
2006/06/26 Javascript
JQuery 绑定select标签的onchange事件,弹出选择的值,并实现跳转、传参
2011/01/06 Javascript
jquery等宽输出文字插件使用介绍
2013/09/18 Javascript
简单实现限制uploadify上传个数
2015/11/16 Javascript
JS实现图片高亮展示效果实例
2015/11/24 Javascript
jQuery插件formValidator自定义函数扩展功能实例详解
2015/11/25 Javascript
vue2.0多条件搜索组件使用详解
2020/03/26 Javascript
EasyUI框架 使用Ajax提交注册信息的实现代码
2017/09/27 Javascript
解决layui的form里的元素进行动态生成,验证失效的问题
2019/09/14 Javascript
uni app仿微信顶部导航条功能
2019/09/17 Javascript
node省市区三级数据性能测评实例分析
2019/11/06 Javascript
Egg Vue SSR 服务端渲染数据请求与asyncData
2019/11/24 Javascript
vue excel上传预览和table内容下载到excel文件中
2019/12/10 Javascript
vue实现购物车功能(商品分类)
2020/04/20 Javascript
详解Vue.js3.0 组件是如何渲染为DOM的
2020/11/10 Javascript
[15:58]DOTA2国际邀请赛采访专栏:Tongfu.Sansheng&KingJ,DK.rOtk
2013/08/08 DOTA
python实现定时播放mp3
2015/03/29 Python
使用memory_profiler监测python代码运行时内存消耗方法
2018/12/03 Python
DJango的创建和使用详解(默认数据库sqlite3)
2019/11/18 Python
tensorflow对图像进行拼接的例子
2020/02/05 Python
windows下Pycharm安装opencv的多种方法
2020/03/05 Python
团队精神的演讲稿
2014/05/14 职场文书
管理提升方案
2014/06/04 职场文书
房屋出售授权委托书
2014/10/12 职场文书
应届毕业生求职简历自我评价
2015/03/02 职场文书
学生会主席任命书
2015/09/21 职场文书
2016七一建党节慰问信
2015/11/30 职场文书
求职自荐信该如何书写?
2019/06/24 职场文书
table不让td文字溢出操作方法
2022/12/24 HTML / CSS