Vuex源碼學習(八)模塊的context如何被建立以及它的做用

你不知道action與mutation怎麼被調用的?趕忙回去看啊Vuex源碼學習(七)action和mutation如何被調用的(調用篇))vue

上兩個小節已經講述了commit與dispatch如何調用mutation與action的,可是action中有幾個參數感受涉及到了一些咱們遺漏(故意不講)的點。ajax

模塊的context

在installModule的時候 給每一個模塊綁定了一個屬性context。 經過makeLocalContext函數建立的,在註冊action、mutation和getters都有使用。這個context是什麼呢?vuex

makeLocalContext函數建立了一個什麼東西

返回值local對象 由兩個方法、兩個屬性構成的。

這個目的是什麼?建立局部模塊的dispatch、commit、getters、state

也就是這個東西

咱們按照類型分析bash

  1. dispatch與commit
// 查看全名,若是沒有全名 多是根模塊或者沒有設置命名空間
const noNamespace = namespace === '';
// 若是沒有全名 就使用全局(store)上的disptach
// 有全名的話 構建一個新的dispatch 
// 這個新的dispatch仍然接收三個參數(與store上的dispatch同樣)
// 
dispatch: noNamespace ? store.dispatch : (_type, _payload, _options) => { 
      //unifyObjectStyle 對額外傳入的_options沒有任何處理 只是肯定一下位置
      const args = unifyObjectStyle(_type, _payload, _options)
      // options 值沒有發生變化
      const { payload, options } = args
      let { type } = args
      // 在disptach的時候是否指定選擇root(根)
      // 若是options設置爲{root : true} 那麼就會跳過下面
      if (!options || !options.root) {
        // 拼接真正的名字
        type = namespace + type
        if (process.env.NODE_ENV !== 'production' && !store._actions[type]) {
          console.error(`[vuex] unknown local action type: ${args.type}, global type: ${type}`)
          return
        }
      }
      // 調用(補全名字後)的action
      return store.dispatch(type, payload)
    },
複製代碼

這段代碼咱們能夠看出來,local對象(也就是模塊的context屬性)中的dispacth會在未指定使用根模塊名字時,會把dispatch調用的名字強行加上這個模塊的全名,用這個dispatch調用的action都會變成你這個模塊下的action函數

因此local中的dispatch與store中的disptach有什麼不一樣

通俗的講 咱們想要調用A模塊(有命名空間的某個action B)須要作的是post

this.$store.dispatch('A模塊的全名/B的名字'); 
複製代碼

在A模塊的action中想要使用dispatch來作一些事情。學習

actions.js
export const ajaxGetUserName = ({dispatch})=>{
    // 這個時候用dispatch調用本身模塊內的其他的action不須要加上全名
    dispatch('ajaxGetUserAge');
    // 想要變成和根模塊同樣的dispatch 須要加上一個options註明{root : true}
    // 這個時候dispatch就會變成全局的 不會主動幫你拼接全名了
}

export const ajaxGetUserAge = () => {
    // do something
}
複製代碼

同理local對象下的commit也是作了一樣的事情,ui

這裏就很少加解釋了,相信聰明的你早就能夠觸類旁通了。

兩個方法說完了,下面該講兩個屬性了this

  1. getters與state

這兩個屬性就是咱們的getters與state,可是這是咱們local對象中,也就是局部模塊下的getters與state。getters與state如何建立的 getters 首先判斷全名是否是爲空,爲空就返回store對象的getters,有的話就建立局部getters。與其說是建立不如說是代理lua

如何建立局部的getters? 代理的方式

makeLocalGetters源碼

function makeLocalGetters (store, namespace) {
  // 設計思想
  //其實咱們並不須要建立一套getters,
  // 只要咱們在local中經過getters來獲取一些局部模塊的值的時候,
  // 能夠被代理到真正存放這些getters的地方。
  
  // 建立代理對象
  const gettersProxy = {}
  // 找到切割點
  const splitPos = namespace.length
  Object.keys(store.getters).forEach(type => {
    // skip if the target getter is not match this namespace
    // 得去getters裏面找一下有沒有這個namespace爲前綴的getter。
    // 沒有就找不到了
    if (type.slice(0, splitPos) !== namespace) return

    // extract local getter type
    // 拿到模塊內註冊的那個局部的getter名字
    // 全名是set/getName
    // localType就是getName
    const localType = type.slice(splitPos)

    // Add a port to the getters proxy.
    // Define as getter property because
    // we do not want to evaluate the getters in this time.
    // 完成代理任務,
    // 在查詢局部名字是被代理到對應的store.getters中的(全名)getter
    Object.defineProperty(gettersProxy, localType, {
      get: () => store.getters[type],
      enumerable: true
    })
  })
  //返回代理對象
  return gettersProxy
}
複製代碼

建立局部的getters就是一個代理的過程,在使用模塊內使用(沒有加上命名空間的)getters的名字,會被代理到,store實例上那個真正的(全名的)getters。

state 這個相對來講就簡單不少了

與代理相似,只是state只須要代理到state中對應那個模塊的state,這個就比較簡單了。

建立完畢

context是如何被建立的你們已經比較瞭解了。context的做用是什麼? (local就是contenxt)以前說過註冊mutation、action、getters都用到了local。用他們幹什麼?一一介紹

1. 註冊mutation

咱們註冊的mutation在被commit調用時,使用的state是局部的state,當前模塊內的state,因此不用特殊方式mutation沒法更新父(祖先)模塊和兄弟模塊的內容。

2. 註冊dispatch

dispatch是能夠調用到模塊內的mutation、disptach,也就是說它有更新模塊內數據的能力,

可是隻給了dispatch傳入了store的getters與state(雖然有了這倆你想要什麼放在vuex的數據都能獲得),並無給store的dispatch與mutation。

這就說名dispatch能夠查看store中的全部數據,你放在vuex裏面的數據我均可以看,可是你想改不使用特殊手段,很差意思只能改本身模塊的。

3. 註冊getters

getters並無改變數據的能力,你願意怎麼操做數據均可以,模塊內的數據,全模塊的數據均可以給你,你願意怎麼計算均可以。

在註冊中咱們能夠看到,vuex對這個改變數據的權限控制的很嚴格,可是查看數據控制的很鬆,改只能改本身模塊的,查你願意怎麼看都OK。

總結

  1. context(也是local)是通過一個makeLocalContext的函數建立的,裏面有局部的dispatch、commit方法和getters、state屬性。
  2. 局部的方法屬性都是隻能訪問局部模塊內的,除非在使用時額外傳入options({root:true})來解開局部模塊的限制。
  3. 局部的getters是經過makeLocalGetters來實現的,主要思想是依靠代理的方式,把局部的名字的getter代理到store的getters中那個全名的getter。
  4. context 的做用能夠幫助dispatch與commit控制更新數據的權限,幫助模塊內getters拿到局部與全模塊的數據。

這個章節結束,咱們全部和模塊有關的內容就已經完結了。 對於模塊作一個小的總結。

模塊的意義

  1. 模塊與模塊連接把Vuex初始化傳入的內容,整理成一個方便處理的模塊樹(方便)
  2. 模塊讓action、mutation、getters、state都有了本身的全名(設置namespaced爲true),起名字再也不被約束,減小了命名衝突。
  3. 模塊還給action、mutation、getters提供了局部上下文(context)讓模塊內的這些方法和屬性,能夠方便的修改模塊內的數據以及獲取全模塊與模塊內的數據。
  4. dispatch與commit也對模塊進行了全力的支持(不支持不白作了嗎),

因此模塊爲Vuex提供了不少方便,方便的去獲取數據、修改數據。那麼Vuex真正的數據倉庫在哪裏?數據都存儲在哪裏? 咱們下一章見

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

我的公衆號:鹹魚正翻身
相關文章
相關標籤/搜索