Vuex原始碼學習(五)加工後的module

酸楚與甘甜發表於2019-03-27

沒有看過moduleCollection那可不行!Vuex原始碼學習(四)module與moduleCollection

感謝提出程式碼塊和截圖建議的小夥伴

程式碼塊和截圖的區別:

  1. 程式碼塊部分希望大家按照我的引導一行行認真的讀
  2. 程式碼的截圖是希望大家能記住圖中的結構,下面會對整體進行一個分析,而不會一行一行的分析。

但是以後的文章會更偏向於使用程式碼塊,希望大家喜歡。

上一章我們講述了ModuleCollection類的作用,幫助我們把偽(未加工的)模組變成真正的模組,然後把每個模組按照父子與兄弟關係連結起來。那麼真正的模組相比於偽(未加工的)模組多了哪些能力呢?

module提供的方法

Vuex原始碼學習(五)加工後的module
這是module暴露出來的所有方法,以及一個屬性。

先看一下constructor

constructor (rawModule, runtime) {
    this.runtime = runtime
    // Store some children item
    // 建立一個容器存放該模組所有的子模組
    this._children = Object.create(null)
    // Store the origin module object which passed by programmer
    // 存放自己未被加工的模組內容。
    this._rawModule = rawModule
    const rawState = rawModule.state
    // Store the origin module‘s state
    // 建立這個模組的資料容器
    this.state = (typeof rawState === 'function' ? rawState() rawState) || {}
}
複製程式碼

模組的初始化主要是做了以下三件事情

  1. 建立_children屬性用於存放子模組
  2. 建立_rawModule屬性儲存自己模組的偽(未被加工)模組時的內容
  3. 建立state屬性儲存自己模組的資料內容 每個模組都有自己的state。

模組的初始化並沒有做什麼事情,模組提供的方法和屬性才是它的核心, 模組提供了一個namespaced的屬性,以及很多方法,我將模組提供的方法分成兩類。

先說屬性

get namespaced () {
    // 獲取模組的namespaced屬性 確定這個模組有沒有自己的名稱空間
    return !!this._rawModule.namespaced
}
複製程式碼

判斷是否有名稱空間有什麼用?在以後設定getters、mutation、actions時有很大作用,以後再講。

再說方法

模組提供的所有方法都是為了給外部的呼叫,這些方法沒有一個是讓模組在自己的內部使用的。所以我把方法劃分的緯度是,按照這個方法是用於構建模組樹還是用於抽取模組中的內容

構建模組樹的方法:

1.addChild:給模組新增子模組。

addChild (key, module) {
    this._children[key] = module
}
複製程式碼

這個方法實現上很簡單,它是在哪裡被呼叫的呢?大家可以翻開上一章的moduleCollection的內容,在ModuleCollection中完成模組之間的連結,就是使用這個方法給父模組新增子模組。 2. removeChild:移除子模組 Vuex初始化的時候未使用,但可以給你提供靈活的處理模組的能力

removeChild (key) {
    delete this._children[key]
}
複製程式碼
  1. getChild:獲取子模組 獲取子模組的意義是什麼?在以後配置模組的名字時,需要獲取模組的是否設定了名稱空間,獲取名稱空間的屬性模組提供了,再提供一個獲取子模組就都Ok了
getChild (key) {
    return this._children[key]
}
複製程式碼
  1. updateChild:更新模組的_ra wModule屬性(更新模組的未加工前的模組內容),Vuex中未使用
update (rawModule) {
    this._rawModule.namespaced = rawModule.namespaced
    if (rawModule.actions) {
      this._rawModule.actions = rawModule.actions
    }
    if (rawModule.mutations) {
      this._rawModule.mutations = rawModule.mutations
    }
    if (rawModule.getters) {
      this._rawModule.getters = rawModule.getters
    }
}
複製程式碼

Vuex在連結與整合模組的時候使用了其中兩個方法,addChild、getChild。類ModuleCollection在連結時需要找到模組(getChild)然後給模組新增子模組(addChild)的功能,所以這兩個方法是在整合模組時最重要的。

抽取模組中的內容

上面的一組方法,是為了更好的完成模組的連結,給散落的單一模組整理成一個模組樹可以提供便捷的封裝方法,下面要說的方法什麼叫做抽取模組中的內容?將這些方法暴露給外面可以方便的去獲取這個模組內的一些內容來使用。

Vuex原始碼學習(五)加工後的module
forEachValue是Vuex封裝的工具方法,用於遍歷物件的。

export function forEachValue (obj, fn) {
  Object.keys(obj).forEach(key => fn(obj[key], key))
}
複製程式碼

這四個方法作用:

  1. forEachChild : 遍歷模組的子模組
  2. forEachGetter : 遍歷模組中_rawModule.getters 這塊就應該知道 _rawModule的作用了,我把模組未加工時會有getters屬性,存放這個模組所有的getters方法(vuex的基本用法就不多講了),然後遍歷,
  3. forEachMutation : 和forEachGetter類似,只是換成了遍歷mutations
  4. forEachAction : 和forEachGetter類似,只是換成了遍歷actions

這四個方法就是遍歷這些內容,有意義嗎?

意義很大,目前_rawModule上這些getters、mutations、actions屬性並不會生效,只是單純的一個屬性,如何讓他們可以成為那種,被dispatch、commit使用的那種方法呢?先給大家一個小提示,mutations、actions都是要被註冊的,註冊之前總要獲取到這些內容,具體的實現方式後面的章節會詳細講述,

總結

加工後真正的module(我們稱由Module這個類例項化出來為真正的module)只是快取了一些內容,並且給外界提供了一堆方便高效的方法。這些方便高效的方法為之後的註冊action、mutation。整合state都起了很關鍵的作用。所以說module這個小單元為下面的程式碼提供了很大便利, 額外思考我們對一段內容需要頻繁的處理並且處理方式大同小異的時候,是不是可以像module一樣整理成一個物件,然後給外界提供一些方法。(有一種物件導向思想)

下一章講述action和mutation是如何呼叫的

我是一個應屆生,最近和朋友們維護了一個公眾號,內容是我們在從應屆生過渡到開發這一路所踩過的坑,已經我們一步步學習的記錄,如果感興趣的朋友可以關注一下,一同加油~

個人公眾號:鹹魚正翻身

相關文章