Vue-router(3.1.6)源码阅读——路由的安装

2020-04-10  本文已影响0人  李牧敲代码

Vue提供了全局的use方法去安装插件,使用use后会自动执行插件里的intall方法来安装:

/* @flow */

import { toArray } from '../util/index'

export function initUse (Vue: GlobalAPI) {
  Vue.use = function (plugin: Function | Object) {
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))//保存Vue上已经有的插件
    if (installedPlugins.indexOf(plugin) > -1) {
      return this
    }

    // additional parameters
    const args = toArray(arguments, 1)

    args.unshift(this)//让每个插件的第一个参数都能拿到Vue
    if (typeof plugin.install === 'function') {
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {
      plugin.apply(null, args)
    }
    installedPlugins.push(plugin)
    return this
  }
}

这就是use的所有源码,很简单,先保存一份Vue已有的插件,然后看下新安装的插件是否存在,存在则退出,否则判断插件的install方法是否是函数或者是本身是函数,是则调用,然后返回Vue.
PS: 并且每个插件的install方法的第一个参数都能拿到vue

再看vue-router的install定义:

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-router只安装一次

  _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(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)//将_route变为响应式的
      } else {
        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
      }
      registerInstance(this, this)
    },
    destroyed () {
      registerInstance(this)
    }
  })

  Object.defineProperty(Vue.prototype, '$router', {//这样每个vue实例都能访问了
    get () { return this._routerRoot._router }
  })

  Object.defineProperty(Vue.prototype, '$route', {
    get () { return this._routerRoot._route }
  })

  Vue.component('RouterView', View)//定义了<router-view>组件
  Vue.component('RouterLink', Link)//定义了<router-link>组件

  const strats = Vue.config.optionMergeStrategies
  // use the same hook merging strategy for route hooks
  strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created//对3个钩子都采用created的策略
}

可以看到这个install做了几件事:

  1. 将Vue保存给_Vue.免得每次都要import
  2. 通过Vue.mixin给每个组件入住beforeCreate和destroyed两个构造函数
  3. 通过Object.defineProperty师德我们能通过Vue.route和Vue.router访问route和router。
  4. 注册了<router-view>和<router-link>2个组件使得我们全局可以使用。

总结:

1. Vue提供了全局的use方法去安装插件,使用use后会自动执行插件里的intall方法来安装,并且每个插件的install方法的第一个参数都能拿到vue
2. install方法将Vue保存给_Vue.免得每次都要import
3. install方法通过Vue.mixin给每个组件入住beforeCreate和destroyed两个钩子函数
4. install方法通过Object.defineProperty使得我们能通过Vue.$route和Vue.$router访问route和router。
5. install方法注册了<router-view>和<router-link>2个组件使得我们全局可以使用。

返回目录

上一篇下一篇

猜你喜欢

热点阅读