Vuex源碼閱讀(二) store內的getters實現邏輯,介紹Vuex對getter進行了哪些處理。 ...
1. 準備工作
1) 創建一個store,state只包含一個count成員:
new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++; } }, actions: { incrementOfActive: ({ commit }) => { commit('increment'); } }, getters: { countOfGetter: (state) => { return state.count; } } });
2) 創建一個Vue對象,並設置store
window.DEMO_VM = new Vue({ el: '#app', store });
2. Vuex對getter做了哪些處理
通過閱讀Vuex的源碼,發現對getter做了下麵處理
2.1 進行局部化
說明:當創建Vuex.Store時,如果內部嵌套了多個stroe(Module),將進行局部化,目的是為了Module各自的getters都保持對各自state的訪問。
代碼:
function registerGetter(store, type, rawGetter, local) { if (store._wrappedGetters[type]) { if (__DEV__) { console.error(`[vuex] duplicate getter key: ${type}`); } return; } store._wrappedGetters[type] = function wrappedGetter(store) { return rawGetter( local.state, // local state local.getters, // local getters store.state, // root state store.getters // root getters ); }; }
2.2 註冊為計算屬性
說明:初始化內部變數_vm,將getter註冊為_vm的計算屬性。
// 獲取getters內的每個getter封裝到_vm const wrappedGetters = store._wrappedGetters; const computed = {}; forEachValue(wrappedGetters, (fn, key) => { computed[key] = partial(fn, store); Object.defineProperty(store.getters, key, { get: () => { return store._vm[key]; }, enumerable: true // for local getters }); }); store._vm = new Vue({ data: { $$state: state }, computed });
3. 解析邏輯
3.1 $store.getters.countOfGetter值從哪裡來
說明:雖然我們創建的countOfGetter的內部為"return state.count;",難道我們每次調用countOfGetter都是執行了對應的函數嗎?
從2.2節的源碼上看,Vuex對countOfGetter設置了get特性,每次調用都是從_vm.countOfGetter獲取。
所以當調用 window.DEMO_VM.$store.getters.countOfGetter 時 → 實際上從返回為 window.DEMO_VM.$store._vm.countOfGetter。
這裡要註意一點store.getters都被註冊為了_vm的計算屬性。
官方對計算屬性好處介紹:“計算屬性是基於它們的響應式依賴進行緩存的。只在相關響應式依賴發生改變時它們才會重新求值。”
總結:這樣子也進一步說明store.getters保留了緩存特性。
3.2 修改了state,getters為什麼會變更
說明:跟上面的說的getters註冊為計算屬性一樣,_vm綁定了state與getters對應的關係,當變更state時,對應的getter也會發生改變。
4. 問題
4.1 為何不直接在組件外修改state?
既然可以通過"window.DEMO_VM.$store.state.count = 4" 這樣操作來修改state,為什麼還需要mutations、actions?
有下麵幾個原因:
1) 統一規範。如果都像這樣在外部直接修改state,那麼整個Vuex體系就會亂掉,直接當成了全局變數(緩存)來使用了。
2) hooks:mutations、actions內部的調用了都附加了Subscribe的處理。
End Web開發之路系列文章 菜單載入中...