$router来历, $store来历,vue 插件机制, vue-router,vue-vuex

1.使用Vuex,Vue.use(Vuex),搞明白Vue.use 都做了什么

Vue 源码src/core/global-api/use.js

/* @flow */

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

export function initUse (Vue: GlobalAPI) {
  Vue.use = function (plugin: Function | Object) {
    /* istanbul ignore if */
    if (plugin.installed) {
      return
    }
    // additional parameters
    const args = toArray(arguments, 1)
    args.unshift(this)
    if (typeof plugin.install === 'function') {
      plugin.install.apply(plugin, args)
    } else {
      plugin.apply(null, args)
    }
    plugin.installed = true
    return this
  }
}

从Vue.use这里可以看出入参plugin,首先判断plugin安装状态,安装直接返回,没有安装则继续下面的流程

const args = toArray(arguments, 1) 为Vue.use(Vuex, ...),...省略的参数,并转换成一个数组,args.unshift(this)将this放入到args的第一向,如果plugin.install 是一个方法就执行plugin.install.apply(plugin, args); 使用apply调用plugin.install 方法,并将该方法里面的this指向plugin,args为数组(apply用法大家可以自行百度)

plugin.install.apply(plugin, args):执行plugin.install 执行上下文为plugin,args为[Vue,...其他参数];

plugin.apply(null, args): plugin 执行上下文为null,args args为[Vue,...其他参数];

2.查看plugin.install 的实现,Vuex 是plugin.install 为一个方法,vue-router则直接是导出一个function

a.

      vuex/src/index.js

function install (_Vue) {
  if (Vue) {
    console.error(
      '[vuex] already installed. Vue.use(Vuex) should be called only once.'
    )
    return
  }
  Vue = _Vue
  applyMixin(Vue)
}

// auto install in dist mode
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue)
}

export default {
  Store,
  install,
  version: '__VERSION__',
  mapState,
  mapMutations,
  mapGetters,
  mapActions
}

install 方法如上,install的参数为上方调用的args [Vue, ...其他参数], _Vue即Vue

b.调用applyMixin,如下

export default function (Vue) {
  const version = Number(Vue.version.split('.')[0])

  if (version >= 2) {
    const usesInit = Vue.config._lifecycleHooks.indexOf('init') > -1
    Vue.mixin(usesInit ? { init: vuexInit } : { beforeCreate: vuexInit })
  } else {
    // override init and inject vuex init procedure
    // for 1.x backwards compatibility.
    const _init = Vue.prototype._init
    Vue.prototype._init = function (options = {}) {
      options.init = options.init
        ? [vuexInit].concat(options.init)
        : vuexInit
      _init.call(this, options)
    }
  }

  /**
   * Vuex init hook, injected into each instances init hooks list.
   */

  function vuexInit () {
    const options = this.$options
    // store injection
    if (options.store) {
      this.$store = options.store
    } else if (options.parent && options.parent.$store) {
      this.$store = options.parent.$store
    }
  }
}

调用default function,判断vue 版本,>2.0,Vue.mixin(usesInit ? { init: vuexInit } : { beforeCreate: vuexInit }),使用mixin混入init或者是beforeCreate 生命周期函数中,当生命周期函数调用时候就执行混入的方法

vuexInit, 查看组件上面的$options属性是否存在store 属性(根节点传入的store),否则查看该组件的父组件是否存在$store(一般来讲必须会存在的,可以形成每次都是查找父组件的$store,就会形成每个组件都具备$store 属性)

 

 

3.vue-router 直接导出一个function,会进入1.initUse 中的plugin.apply(null, args)该分支

vue-router/src/install.js

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

export let _Vue

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

  _Vue = Vue

  Object.defineProperty(Vue.prototype, '$router', {
    get () { return this.$root._router }
  })

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

  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._router = this.$options.router
        this._router.init(this)
        Vue.util.defineReactive(this, '_route', this._router.history.current)
      }
      registerInstance(this, this)
    },
    destroyed () {
      registerInstance(this)
    }
  })

  Vue.component('router-view', View)
  Vue.component('router-link', Link)

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

 

Object.defineProperty(Vue.prototype, '$router', {
    get () { return this.$root._router }
  })

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

直接挂载在Vue.prototype原型上面,组件内部可以使用this.$router,this.$route

this.$router每次会调用Vue.prototype.$router 的get 放方法

this.$route每次会调用Vue.prototype.$router 的get 放方法

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值