你不知道action與mutation怎麼被調用的?趕忙回去看啊Vuex源碼學習(七)action和mutation如何被調用的(調用篇))vue
上兩個小節已經講述了commit與dispatch如何調用mutation與action的,可是action中有幾個參數感受涉及到了一些咱們遺漏(故意不講)的點。ajax
在installModule的時候 給每一個模塊綁定了一個屬性context。
經過makeLocalContext函數建立的,在註冊action、mutation和getters都有使用。這個context是什麼呢?vuex
返回值local對象 由兩個方法、兩個屬性構成的。segmentfault
這個目的是什麼?建立局部模塊的dispatch、commit、getters、state函數
也就是這個東西學習
咱們按照類型分析this
// 查看全名,若是沒有全名 多是根模塊或者沒有設置命名空間 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都會變成你這個模塊下的actionlua
通俗的講
咱們想要調用A模塊(有命名空間的某個action B)須要作的是spa
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也是作了一樣的事情,
這裏就很少加解釋了,相信聰明的你早就能夠觸類旁通了。
兩個方法說完了,下面該講兩個屬性了
這兩個屬性就是咱們的getters與state,可是這是咱們local對象中,也就是局部模塊下的getters與state。getters與state如何建立的
getters
首先判斷全名是否是爲空,爲空就返回store對象的getters,有的話就建立局部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。
{root:true}
)來解開局部模塊的限制。這個章節結束,咱們全部和模塊有關的內容就已經完結了。
對於模塊作一個小的總結。
因此模塊爲Vuex提供了不少方便,方便的去獲取數據、修改數據。那麼Vuex真正的數據倉庫在哪裏?數據都存儲在哪裏?
咱們下一章見