從vue-router裏學習插件寫法

圖片描述

前言

最近在看vue-router和vuex的源碼,都會有本身的install方法,而後經過mixin綁定到生命週期裏vue

vue.use

vue.use兼容帶install和不帶install,這兩種註冊的方式均可以,只是install會更容易擴展node

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實例上去vue-router

相關文章
相關標籤/搜索