天天看點

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
    }
  }
}
      

繼續閱讀