前言

最近在看vue-router和vuex的源码,都会有自己的install方法,然后通过mixin绑定到生命周期里

vue.use

vue.use兼容带install和不带install,这两种注册的方式都可以,只是install会更容易扩展

export function initUse (Vue: GlobalAPI) {  Vue.use = function (plugin: Function | Object) {      <!-- 已经use的插件数组 -->    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))    if (installedPlugins.indexOf(plugin) > -1) {      return this    }    // additional parameters    <!-- 把传入的参数整理成数组 -->    const args = toArray(arguments, 1)    <!-- 默认第一个参数是vue对象 -->    args.unshift(this)    <!-- 判断带不带install方法 -->    if (typeof plugin.install === 'function') {      plugin.install.apply(plugin, args)    } else if (typeof plugin === 'function') {      plugin.apply(null, args)    }    installedPlugins.push(plugin)    return this  }}

vue-router

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(vm, callVal)    }  }<!-- 通过mixin添加生命周期 -->  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)    }  })  <!-- 所有实例中 this.$router 等同于访问 this._routerRoot._router -->  Object.defineProperty(Vue.prototype, '$router', {    get () { return this._routerRoot._router }  })<!-- 所有实例中 this.$route 等同于访问 this._routerRoot._route -->  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}

总结

要写一个vue的插件,可以是带install或不带,然后在里面通过mixin,绑定prototype,调用component等方法去注册到vue实例上去