使用

日常我们使用 vue-router 时:

在 template 中我们用 <router-link> 来做路由跳转,用 <router-view> 来做路由跳转后的展示。

<p><router-link to="/foo">Go to Foo</router-link><router-link to="/bar">Go to Bar</router-link>
</p>
<router-view></router-view>
复制代码

在 js 中,先用 Vue.use 来安装 vue-router,然后 new 一个 VueRouter 实例,最后将实例注入到 Vue 实例中。

Vue.use(VueRouter)const router = new VueRouter({routes
})const app = new Vue({router
}).$mount('#app')
复制代码

这样就实现了一个路由系统。我把这个过程称为路由的安装与初始化

那么这个过程里,vue-router 做了什么事情呢?接下来就来一探究竟。

对了,我选的是 vue-router v2.0.1 的代码来阅读。

Flow

在阅读 vue-router 的源码前,我们需要了解一下 Flow。

Flow 是 Facebook 的 JavaScript 静态类型检查工具,语法跟 TypeScript 有点类似。

源码里就用了 Flow 来做静态类型检查。Vue-router 在 Flow 中的自定义类型存放在项目里的 flow 目录下。

想必你会问,为什么不用 TypeScript 而是用 Flow 呢?这个作者的回答是最权威的,戳 这里 了解一下吧。

猜想

在阅读之前,我们先来简单猜想一下,路由安装与初始化会做哪些事情。

  1. 注册两个组件,<router-link><router-view>
  2. 通过 hashhistory 来实现前端路由
  3. 处理作为参数传入的路由,匹配路由
  4. 将 VueRouter 对象实例注入 Vue 实例中
  5. ......

install

正式开始阅读代码了,来验证上面的猜想是否正确吧。

src/index.js 文件中,有一段这样的代码:

import { install } from './install'// ...VueRouter.install = installif (inBrowser && window.Vue) {window.Vue.use(VueRouter)
}
复制代码

我们知道调用了 Vue.use 就会默认去调用 install 方法,所以跳转到 src/install.js 文件中。

找到这段代码:

Vue.mixin({beforeCreate () {if (this.$options.router) {this._router = this.$options.routerthis._router.init(this)Vue.util.defineReactive(this, '_route', this._router.history.current)}}
})
复制代码

这段代码,就是将 VueRouter 对象实例注入 Vue 实例中,赋值给属性 _router,同时创造了另一个属性 _route

注意,这里还会调用 init 方法,接下来会阅读到。

下划线表示私有属性,如果需要给外部使用,则需要暴露一个方法或外部属性出来:

Object.defineProperty(Vue.prototype, '$router', {get () { return this.$root._router }
})Object.defineProperty(Vue.prototype, '$route', {get () { return this.$root._route }
})
复制代码

这样子,就可以在 Vue 的组件里 this.$routerthis.$route 的调用。

最后注册了两个全局组件,<router-link><router-view>

Vue.component('router-view', View)
Vue.component('router-link', Link)
复制代码

这里有一个需要注意的点,Vue.use 会调用 install 方法,即以上的代码都会执行,但是 Vue 的 beforeCreate 钩子是在 new Vue 的时候才会执行。

意思就是 new VueRouter 会在 beforeCreate 之前执行。即会先执行 VueRouter 的 constructor 构造函数。

constructor

来看看 VueRouter 的 constructor 构造函数做了哪些事情吧。constructor 的代码不多,主要是初始化一些属性。

constructor (options: RouterOptions = {}) {this.app = nullthis.options = optionsthis.beforeHooks = []this.afterHooks = []this.match = createMatcher(options.routes || [])let mode = options.mode || 'hash'this.fallback = mode === 'history' && !supportsHistoryif (this.fallback) {mode = 'hash'}if (!inBrowser) {mode = 'abstract'}this.mode = mode
}
复制代码

里面的 createMatcher 先跳过,这又是另一大块,暂时不管。

可以看到后面的代码就是在设置 this.mode,即路由模式

默认是 hash 模式,如果设置了 history 还得判断支持该种模式不,不支持则下降为默认的模式。如果代码不是运行在浏览器而是在 node 端,则设置为 abstract 模式,这个也先跳过哈哈哈。

beforeCreate 会调用 VueRouter 的 init 方法,来看看里面做了什么初始化工作吧。

init

init 方法是这么被调用的:

this._router.init(this)
复制代码

这里的 this 指向的是 Vue 实例。

再来看看 init 里面的实现(过滤掉部分代码):

init (app: any /* Vue component instance */) {this.app = appconst { mode, options, fallback } = thisswitch (mode) {case 'history':this.history = new HTML5History(this, options.base)breakcase 'hash':this.history = new HashHistory(this, options.base, fallback)breakcase 'abstract':this.history = new AbstractHistory(this)breakdefault:assert(false, `invalid mode: ${mode}`)}this.history.listen(route => {this.app._route = route})
}
复制代码

init 实现的是,通过刚刚 constructor 设置的 mode 来生成一个新的属性 this.history

this.history 是根据不同的 mode 来 new 出不同的对象实例。像 history 模式就用 HTML5History,hash 模式就用 HashHistory

对象里面的实现待以后再深入吧。现在我们只要知道有这么一个新属性 this.history 即可。

this.history 通过调用 listen 方法,将更新 _route 的操作保存起来,在以后更新路由的时候,会执行该操作来更新 _route。讲了跟没讲一样哈哈,没关系,现在只要知道有这代码存在就行了。

回顾

VueRouter 的路由安装与初始化做了哪些事情。按顺序来:

(一)

调用 install 方法,注册两个组件,<router-link><router-view>

(二)

new 了 VueRouter 实例,调用 contructor 构造函数,初始化了一些属性,其中包括 mode 属性,用来保存路由模式。

(三)

new 了 Vue 实例,调用其 beforeCreate,将 VueRouter 对象实例注入 Vue 实例中,并调用 install 方法。install 方法则在根据不同的路由模式新增一个 history 属性。history 属性保存的对象里面又是一片天地,待续。

vue-router 源码:路由的安装与初始化相关推荐

  1. springboot+vue+mysql外卖点餐管理系统源码(包安装+讲解)

     博主介绍:✌在职Java研发工程师.专注于程序设计.源码分享.技术交流.专注于Java技术领域和毕业设计✌ 项目名称 springboot+vue+mysql外卖点餐管理系统源码(包安装+讲解) 视 ...

  2. 【Vue.js源码解析 一】-- 响应式原理

    前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:建议通过左侧导航栏进行阅读 课程目标 Vue.js 的静态成员和实例成员初始化过程 首次渲染的过程 数据响应式原理 – 最核心的特性之一 准备工作 ...

  3. 精读《react-snippets - Router 源码》

    造轮子就是应用核心原理 + 周边功能的堆砌,所以学习成熟库的源码往往会受到非核心代码干扰,Router 这个 repo 用不到 100 行源码实现了 React Router 核心机制,很适合用来学习 ...

  4. Vue.js 框架源码与进阶 - Vue.js 源码剖析 - 响应式原理

    文章目录 一.准备工作 1.1 Vue 源码的获取 1.2 源目录结构 1.3 了解 Flow 1.4 调试设置 1.5 Vue 的不同构建版本 1.6 寻找入口文件 1.7 从入口开始 二.Vue ...

  5. zabbix 3.2.2 server端(源码包)安装部署 (一)【转】

    环境准备: 操作系统 CentOS 6.8 2.6.32-642.11.1.el6.x86_64 zabbix server 172.16.10.150 zabbix agent 172.16.10. ...

  6. java 环境部署——java源码包的安装——java-rpm包的安装

    1.java 源码包的安装 # tar -xf jdk-8u201-linux-x64.tar.g# mkdir /usr/java# cp jdk1.8.0_201/ /usr/java 设置jav ...

  7. 软件的安装(包括yum仓库与源码包的安装)

    软件的安装 实验背景: 为了提高Linux服务器的易用性.扩展功能,安装软件包是管理员必备的技能,这其中又以RPM方式的安装操作最基础.最常用. 另外有时候需要解决依赖关系,要配置yum仓库.YUM ...

  8. 【CyberSecurityLearning 37】网络安全常用Linux系统命令以及 源码包的安装过程

    目录 一.Linux系统中以下目录的作用 二.linux系统中以下颜色表示的文件类型 三.Linux系统基础命令 1.uname -a  内核版本号查询 2.fdisk  -l  查看硬盘以及分区 3 ...

  9. vue.js源码学习分享(一)

    今天看了vue.js源码  发现非常不错,想一边看一遍写博客和大家分享 /*** Convert a value to a string that is actually rendered. *转换一 ...

最新文章

  1. 基于matlab的64QAM,通信调制体制设计之64QAM性能分析MATLAB仿真及代码
  2. 【Android】Android程序自己主动更新
  3. css属性 background
  4. 手写自己的MyBatis框架-V2.0 可优化之处
  5. Go中new和make的区别
  6. 深入了解Java 8中的可选类API
  7. Spring Boot 配置SSL 实现HTTPS
  8. react 更新input 默认值setfieldsvalue_值得收藏的React知识点查漏补缺
  9. perl DBI 总结
  10. golang控制台颜色输出(for windows)
  11. pcb只开窗不镀锡_只因为把高速PCB旋转了一下,结果地覆天翻……
  12. NSNotFound
  13. 从 JavaScript 到 TypeScript 6 - Vue 引入 TypeScript
  14. Atitit. 数据库-----catalog与schema的设计区别以及在实际中使用 获取数据库所有库表 java jdbc php  c#.Net
  15. 一个老程序员的心里话!
  16. 潭州教育学python怎么样_在潭州教育学原画两个月的感受
  17. 2013年Devoxx法国-第3天
  18. mybatis plus 格式话_MyBatisPlus学习整理(二)
  19. java 加密word_Java 加密和解密PDF文档
  20. linux can命令详解,Linux CAN编程详解

热门文章

  1. linux系统测试报告,[Linux-文件系统测试] -- Bonnie++测试
  2. java 模仿支付成功_揭秘Java工程师薪资为何这么高,教你如何成为架构师拿50W年薪!...
  3. 获取当前经纬度php腾讯地图,PHP腾讯地图经纬度转百度地图经纬度
  4. python函数分为_python 函数
  5. python手机代码识别数字_python实现kNN算法识别手写体数字的示例代码
  6. m3u8文件在手机上用什么软件看_新技能Get!教你制作m3u8文件 创建属于自己的直播视频列表...
  7. c++:MFC中sqlite3的使用(附实际案例)
  8. Win 10操作系统环境下python3.7 实现sklearn 安装
  9. 有三AI高质量内容推荐(广告)须知
  10. 中国香皂行业产量份额预测与消费需求商机研究报告2022年