VueRouter源码分析--install方法

1.入口

一般情况下,在一个项目中入口文件为index.js。
VueRouter的源码index.js中有一小部分是关于install方法的,也是我们分析install方法的入口。

import { install } from './install'
// 挂载install;
VueRouter.install = install
VueRouter.version = '__VERSION__'
// 判断如果window上挂载了Vue则自动使用插件;
if (inBrowser && window.Vue) {
  window.Vue.use(VueRouter)
}

在这里,可以发现VueRouter的实例以类(对象)方法的形式设置了install属性和version属性。
同时设置了当为浏览器环境且window中包含Vue实例时调用use方法安装VueRouter,需要了解的则是在use方法中调用了VueRouter的install方法

2.方法主体

1. _Vue的写法
在install方法的主体中,首当其冲的是一段对_Vue的处理。

// export一个Vue的原因是可以不将Vue打包进插件中而使用Vue一些方法;
// 只能在install之后才会存在这个Vue的实例;
export let _Vue
export function install (Vue) {
  // 如果已经执行了install方法,则不再重复执行
  if (install.installed && _Vue === Vue) return
  install.installed = true
  // 把 Vue 赋值给全局变量
  _Vue = Vue
  ...
  Vue.xxx
}

因为install方法在执行的时候,传入的参数就是在调用use方法的Vue实例,所以这里可以使用一个全局变量类型的_Vue来接收Vue,使得在VueRouter中的其他地方也可以调用到全局变量_Vue从而可以使用一些Vue中的方法。
同时,这也使得Vue可以不被引入,减少了代码的打包体积。
实际上,这种写法在Vue的插件中很常用,Vuex中也是这种形式来接收Vue
2. mixin混入
mixin混入功能,在我看来就是使用了类似于obj.prototype.xxx形式添加了新的功能方法,从而使得该功能可以被子类调用。

// 采用混入方式,在beforeCreate和destoryed方法中处理路由相关操作
Vue.mixin({
  beforeCreate () {
    // 如果已经挂载了router属性,
    if (isDef(this.$options.router)) {
      // 保存vue实例到this._routerRoot
      this._routerRoot = this
      // 保存vue实例数据中的router,即为挂载的route实例
      this._router = this.$options.router
      // router实例进行初始化
      this._router.init(this)
      // 添加属性_route,实现双向绑定,触发组件渲染,存放当前页面路径
      Vue.util.defineReactive(this, '_route', this._router.history.current)
    } else {
      // 将每一个组件的_routerRoot都指向根Vue实例;
      this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
    }
    // 注册VueComponent 进行Observer处理;
    registerInstance(this, this)
  },
  destroyed () {
    // 注销VueComponent
    registerInstance(this)
  }
})
  1. Vue实例包括根实例和子实例,根实例可直接进操作,而子实例则需要不断寻找它的父实例,从而使得每一个子实例的_routerRoot都指向Vue根实例。
  2. 这里面有几个变量是需要注意的:
    1. $options下的router即为实例化Vue的时候挂载vue-router实例;
    2. _routerRoot指向我们的Vue根节点;
    3. _router存储的就是我们从$options中拿到的vue-router对象;
    4. _route是一个响应式的路由route对象,存储路由信息。它是通过Vue提供的Vue.util.defineReactive来实现响应式的。

3. 定义两个全局组件

import View from './components/view'
import Link from './components/link'
// 注册全局组件 router-view   router-link
Vue.component('RouterView', View)
Vue.component('RouterLink', Link)

这两个就是可以全局使用的router-link和router-view组件。
两个组件都是函数类组件,具体分析留待后续,暂不展开。
4. 设置两个原型对象

// 给vue实例的原型添加$router属性,
// 使得可以通过this.$router方式调用router相关方法
Object.defineProperty(Vue.prototype, '$router', {
  get () { return this._routerRoot._router }
})
// 给vue实例的原型添加$route属性,
// 使得可以通过this.$route方式调用route相关方法
Object.defineProperty(Vue.prototype, '$route', {
  get () { return this._routerRoot._route }
})

需要了解的东西:

  1. this. r o u t e r 指 向 的 是 t h i s . r o u t e r R o o t . r o u t e r , 即 为 从 router指向的是 this._routerRoot._router ,即为从 routerthis.routerRoot.router,options中拿到的VueRouter对象,所以可以使用push、back、go等方法
  2. this.$route指向的是this._routerRoot._route,即为存储路由信息的响应式对象,所以可以从中获取到query、path、params等属性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端SkyRain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值