vue-router源码解析(二) —— install

系列文章目录

1、vue-router源码解析(一)
2、vue-router源码解析(二) —— install



前言

上一篇简单介绍了下vue-router的源码大体思路框架,本篇详细解析下VueRouter是如何安装挂载的~


一、index.js中的install

VueRouter 对象是在 src/index.js 中暴露出来的,它有一个静态的 install 方法:

// index.js
// 引入install模块
import {
    
     install } from './install'
// 定义VueRouter对象
export default class VueRouter {
    
    
	static install: () => void
	...
}
VueRouter.install = install
...
// 浏览器环境下,若有Vue环境,自动挂载VueRouter插件
if (inBrowser && window.Vue) {
    
    
  window.Vue.use(VueRouter)
}

将导入的Install赋值给了VueRouter对象的install静态方法,在最后判定当为浏览器环境,执行window.Vue.use(VueRouter)挂载插件时,实际上Vue实例的use(VueRouter)就是使用的VueRouter对象自身的install方法,进行插件的安装。
install是一个单独的模块,下面来具体看一下。

二、install.js

import View from './components/view'
import Link from './components/link'

export let _Vue

export function install(Vue) {
    
    
 
  if (install.installed && _Vue === Vue) return
  install.installed = true
  
  _Vue = Vue

  const isDef = v => v !== undefined

  const registerInstance = (vm, callVal) => {
    
    
    let i = vm.$options._parentVnode 
    if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
    
    
      // 这里的 i 就是 registerRouteInstance 方法,调用的就是这个方法
      i(vm, callVal) 
    }
  }

  Vue.mixin({
    
    
    beforeCreate () {
    
    
      if (isDef(this.$options.router)) {
    
    
        this._routerRoot = this 
        this._router = this.$options.router 
        // 路由初始化,建立路由监控
        this._router.init(this)  
        // 响应式定义属性
        Vue.util.defineReactive(this, '_route', this._router.history.current) 
      } else {
    
    
        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
      }
      registerInstance(this, this)
    },
    destroyed() {
    
    
      registerInstance(this)
    }
  })
 
  Object.defineProperty(Vue.prototype, '$router', {
    
    
    get () {
    
     return this._routerRoot._router }
  })
  
  Object.defineProperty(Vue.prototype, '$route', {
    
    
    get () {
    
     return this._routerRoot._route }
  })

  Vue.component('RouterView', View)
  Vue.component('RouterLink', Link)

  const strats = Vue.config.optionMergeStrategies
  // use the same hook merging strategy for route hooks
  strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
}

  • 本模块主要定义了install方法,用于Vue.use(VueRouter)调用来安装VueRouter插件。
  • export let _Vue定义_Vue变量,_Vue = Vue用于保存Vue实例对象, export暴露出去,目的是其他模块方便对Vue实例的引用,使用其方法和属性,而又不用引入整个vue依赖包,增大打包体积。
  • if (install.installed && _Vue === Vue) return判定是否已经安装,定义一个installed属性,若为true且已有Vue的引用(只有调用了install方法才有install.installed = true和 _Vue === Vue),表示已安装过,否则退出install方法。这样可以保证只安装一次。
  • 定义了registerInstance方法,let i = vm.$options._parentVnode 至少存在一个 VueComponent 时, _parentVnode 属性才存在
  • Vue.mixin({...})混入生命周期的处理,在beforeCreate节点响应式定义_route属性,Vue.util.defineReactive(this, '_route', this._router.history.current) ,在destroyed节点销毁实例
  • Object.defineProperty()Vue.prototype上挂载$router,$route属性(只读模式)
  • Vue.component('RouterView', View),Vue.component('RouterLink', Link)全局注册组件

总结

猜你喜欢

转载自blog.csdn.net/qq_36131788/article/details/112769888