本节简单介绍如何安装 vue-router
由前文可知已通过 Vue.use(plugin) 函数注册插件,最后在该函数内部执行 plugin.install() 函数进行安装插件,呢么接下来我们一下安装路由插件的过程。
首先介绍一下 vue-router 源码的入口文件是 /src/index.js,在该文件内定义了 VurRouter 类并定义了静态方法 install() 函数,即为:VueRouter.install = install; 语句,而 install() 函数定义在 /src/install.js 文件内,呢么接下来简单分析一下该函数的内部实现过程。
关于 install() 函数就暂时不上源代码,直接简述其过程。
1、在 install() 函数内部首先通过标志位 install.installed = true; 确保该函数仅仅执行一次,同时又用全局变量 _Vue 接收参数并缓存 Vue 类。
2、接下来贴上其重要逻辑过程的源码,如下图所示:
首先通过 Vue.mixin({ beforeCeate(){}, destroyed(){} }) 函数把生命周期钩子 beforeCeate、destroyed 函数注入到每一个组件内。因为 Vue.mixin(obj) 函数可以将参数 obj 扩展到 Vue.options 属性上,同时组件初始化时会将 Vue.options 属性的内容合并到组件的 vm.$options 属性上,所以才会注入到每一个组件内。
在 new Vue({ el, router, store, ... }) 初始化时会传入路由实例 router 作为参数,然后参数将会被合并到根实例 vm.$options 属性上,所以只能在根实例上直接访问以上参数,子组件实例上无法直接访问。
在生命周期钩子函数 beforeCeate() 内,当 this.$options.router 值存在时,当前 this 即为根实例,否则为子组件实例。对于根实例而言有如下逻辑:
- 定义
this._routerRoot = this;表示自身。 - 定义
this._router = this.$options.router;表示VueRouter实例并缓存,然后执行路由实例的this._router.init()函数。 - 用
defineReactive(this, _route, this._router.history.current)定义为响应式对象,表示当前页面的路由。
对于子组件实例而言,则定义 this._routerRoot = this.$parent._routerRoot || this; 属性,即:去找父组件实例的 _routerRoot 属性,若不存在则赋值为自己。
其次在 Vue.prototype 上定义了 $router、$route 两个属性的 get() 函数,这就是为什么我们可以在子组件中访问 this.$router、this.$route 值。而在 get() 函数内 this._routerRoot 表示根实例,this._routerRoot._router 表示路由实例,this._routerRoot._route 表示当前页面的路由。
3、最后通过 Vue.component() 方法定义了全局的 <router-link> 和 <router-view> 两个组件,这也是为什么我们在写模板的时候可以使用这两个标签。