Vuex的原理 (一、Vue.use(vuex)做了什么?)


Vuex的原理 一

  針對vuex的版本 3.5.1
  • Vue.use(vuex)這個過程中vuex都做了什么?

調用vuex的install方法,判斷Vuex是否已經注冊過了,注冊過了就直接返回,這里使用的是單例模式。
調用applyMixin(Vue)
將初始化vuex的方法(vuexInit)混入到vue的beforeCreate生命周期中;
將$store綁定到每個vue實例中。

源碼解讀
  • 再看install方法之前,我們需要先了解一下vuex.use方法都做了什么,源碼位置位於Vue源碼項目中的 src/global-api/use.js

      Vue.use = function (plugin: Function | Object) {
          const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
          if (installedPlugins.indexOf(plugin) > -1) { // Vue檢測是否已經注冊過這個插件, 如果已經注冊過就直接返回
            return this
          }
    
          // additional parameters
          const args = toArray(arguments, 1) // 把參數截取出來組成一個數組,后面需要作為apply的第二個參數傳入,注意這里不要第一個參數,因為第一個參數是我們的插件,比如(vuex,vueRouter、elementui)等;
          args.unshift(this) // 把Vue作為第一個參數
          if (typeof plugin.install === 'function') {
            plugin.install.apply(plugin, args) // 如果插件有intall方法就直接調用他的install方法,並把args傳入。
          } else if (typeof plugin === 'function') {
            plugin.apply(null, args)
          }
          installedPlugins.push(plugin)
          return this
        }
    
    • 接下來我們看Vuex的install方法,源碼位置在Vuex的 src/store.js
      export function install (_Vue) {
        if (Vue && _Vue === Vue) { // 這里也是判斷Vue是否已經注冊過vuex了,如果注冊過就直接返回,注意vuex是單例模式
          if (__DEV__) {
            console.error(
              '[vuex] already installed. Vue.use(Vuex) should be called only once.'
            )
          }
          return
        }
        Vue = _Vue
        applyMixin(Vue) // 調用applyMixin, 看下這個函數干了啥
      }
    
    • applyMixin 方法 源碼位於 Vue的 src/mixin.js
     export default function (Vue) {
       const version = Number(Vue.version.split('.')[0]) // 獲取vue的版本
    
       if (version >= 2) { // 如果版本大於等於2, 就在vue的beforeCreate中混入vuexInit函數, 接下來看一下vuexInit
         Vue.mixin({ beforeCreate: vuexInit })
       } else { // 這段代碼可以不看, 針對vue低版本的vuex的處理
         // 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 () { // 當我們實例化vue的時候就會調用這個函數了。
         const options = this.$options // 獲取vue的$options
         // store injection
         if (options.store) { // 判斷options中是否存在store屬性,這里就是我們在vue的main.js中實例化Vue時寫的new Vue({store}).$mount('app')
           this.$store = typeof options.store === 'function'
             ? options.store()
             : options.store  // 將vuex綁定到Vue實例的$store屬性上
         } else if (options.parent && options.parent.$store) { 
           /* 這里的代碼的意思是,我們需要在任何Vue的組件中都能通過使用this.$store直接調用vuex,
           所以vuex給我們做了這個工作,如果當前組件的option沒有store屬性,
           就看他的父組件上有沒有,直到拿到store,然后賦值給$store屬性,
           這樣我們就能在Vue的組件中使用this.$store了。*/
           this.$store = options.parent.$store
         }
       }
    

    總結 Vue.use(vuex)

       - 判斷vue是否已經注冊過vuex插件;
       - 將`vuexInit`函數混入到vue的beforeCreate生命周期中;
       - 實例化vue時,會在vue每個實例上添加$store屬性,並將vuex的實例綁定到$store屬性上。
    

個人github地址 https://github.com/ComponentTY/vue-sourcecode/tree/master/vuex


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM