vuex源碼解析01index與install

index.js

index 文件夾主要是爲了導出vuex提供的模塊

import { Store, install } from './store'
import { mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers } from './helpers'
`export default {`
  `Store,`// Store:包含狀態的容器`
  `install,`// install: 提供給Vue.use()全局掛載的install`
  `version: '__VERSION__',`
  `mapState,`// mapState: 展開state的內容`
  `mapMutations,`// mapMutations:展開mutations的內容`
  `mapGetters,`// mapGetters:展開getter的內容`
  `mapActions,`// mapActions:展開actions的內容`
  `createNamespacedHelpers`// createNamespacedHelpers:創建基於命名空間的組件綁定輔助函數` 
}

store.js中的 install函數

我們在使用vuex的時候是vue.use(vuex),這個是怎麼實現的呢?

  1. vue的插件系統,提供了use函數,方便我們引入插件
  2. use函數規定,每個插件都需要編寫install函數,vuex在store.js中提供了install函數
// 這裏的_vue是一個全局變量,用來接收vue
// vue使用插件的方法很簡單,只需Vue.use(Plugins)即可使用插件。在vue中是如何實現的呢?
// 瞭解vue的話,你應該知道,use(),接收一個install方法,這個install由插件開發者定義。
// 最後達到全局註冊組件。
export function install(_Vue) {
  // 判斷已經引入過插件。防止重複引入。其實在vue.use中也會判斷時候已經裝過
  if (Vue && _Vue === Vue) {
    if (process.env.NODE_ENV !== 'production') {
      console.error(
        '[vuex] already installed. Vue.use(Vuex) should be called only once.'
      )
    }
    return
  }
  // 如果沒有引入,調用applyMixin().此方法位於mixin.js
  Vue = _Vue
  applyMixin(Vue)
}

install函數調用applyMixin().此方法位於mixin.js

// 執行vuexInit方法初始化Vuex

// 這裏針對Vue1.0與2.0分別進行了不同的處理
// Vue1.0,Vuex會將vuexInit方法放入Vue的_init方法中,
// Vue2.0,則會將vuexinit混淆進Vue的beforeCreate鉤子中。
export default function (Vue) {
  //獲取vue的版本
  const version = Number(Vue.version.split('.')[0])
  // 如果vue的版本大於2的話,直接調用vuexInit放入beforeCreate鉤子中
  if (version >= 2) {
    // 使用mixin方法,在組件創建前加入vuexInit
    Vue.mixin({ beforeCreate: vuexInit })
  } else {

    // 重寫init,將vuexInit放入init中
    // 先把Vue.prototype._init存放在常量中,防止修改
    const _init = Vue.prototype._init
    Vue.prototype._init = function (options = {}) {
      options.init = options.init
        ? [vuexInit].concat(options.init)
        : vuexInit
      _init.call(this, options)
    }
  }

  // 在 vuexInit 中,將 new Vue() 時傳入的 store 設置到 this 對象的 $store 屬性上,//
  // !!!
  // 注意,因爲每個組件都會被渲染,在上面使用mixin進行了混入,所以vuexInit在組件被創建之前都會被調用。
  // vue渲染組件的方法是先渲染父組件在渲染子組件,深度優先。
  // new Vue() 時傳入的 store,這個時候,store已經掛在最上面的root(根)組件上。
  // 子組件則從其父組件上引用其 $store 屬性進行層層嵌套設置,保證每一個組件中都可以通過 this.$store 取到 store 對象。
  // 通過在根實例中註冊 store 選項,該 store 實例會注入到根組件下的所有子組件中,注入方法是子從父拿,root從options拿。
  function vuexInit() {
    // vue 提供的一個實例屬性,用來獲取Vue實例的自定義屬性(如vm.$options.methods,獲取Vue實例的自定義屬性methods)
    const options = this.$options
    // 如果 new Vue() 時傳入了 store 
    // 如果本身就是父組件
    if (options.store) {
      // 則將store掛在到this上,也就是vue上
      this.$store = typeof options.store === 'function'
        ? options.store()
        : options.store
    } else if (options.parent && options.parent.$store) {
      // 如果某個組件存在父級組件,並且父級組件存在$store,則將該組件上也掛載$store
      this.$store = options.parent.$store
    }
  }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章