輔助函數
Vuex 除了提供我們 Store 對象外,還對外提供了一系列的輔助函數,方便我們在代碼中使用 Vuex,提供了操作 store 的各種屬性的一系列語法糖,下面我們來一起看一下:
mapState
mapState 工具函數會將 store 中的 state 映射到局部計算屬性中。為了更好理解它的實現,先來看一下它的使用示例:
// vuex 提供了獨立的構建工具函數 Vuex.mapState import { mapState } from 'vuex' export default { // ... computed: mapState({ // 箭頭函數可以讓代碼非常簡潔 count: state => state.count, // 傳入字符串 'count' 等同於 `state => state.count` countAlias: 'count', // 想訪問局部狀態,就必須借助於一個普通函數,函數中使用 `this` 獲取局部狀態 countPlusLocalState (state) { return state.count + this.localCount } }) }
當計算屬性名稱和狀態子樹名稱對應相同時,我們可以向 mapState 工具函數傳入一個字符串數組
computed: mapState([ // 映射 this.count 到 this.$store.state.count 'count' ])
即 等價於
computed: mapState([ // 傳入字符串 'count' 等同於 `state => state.count` count: 'count', ])
即 等價於
computed: mapState([ // 映射 this.count 到 this.$store.state.count count: state => state.count, ])
通過例子我們可以直觀的看到,mapState函數可以接受一個對象,也可以接收一個數組,那它底層到底干了什么事呢,我們一起來看一下源碼這個函數的定義:
export function mapState (states) { const res = {} normalizeMap(states).forEach(({ key, val }) => { res[key] = function mappedState () { return typeof val === 'function' ? val.call(this, this.$store.state, this.$store.getters) : this.$store.state[val] } }) return res }
函數首先對傳入的參數調用 normalizeMap 方法,我們來看一下這個函數的定義:
function normalizeMap (map) { return Array.isArray(map) ? map.map(key => ({ key, val: key })) : Object.keys(map).map(key => ({ key, val: map[key] })) }
這個方法判斷參數 map 是否為數組,如果是數組,則調用數組的 map 方法,把數組的每個元素轉換成一個 {key, val: key}的對象;否則傳入的 map 就是一個對象(從 mapState 的使用場景來看,傳入的參數不是數組就是對象),我們調用 Object.keys 方法遍歷這個 map 對象的 key,把數組的每個 key 都轉換成一個 {key, val: key}的對象。最后我們把這個對象數組作為 normalizeMap 的返回值。
回到 mapState 函數,在調用了 normalizeMap 函數后,把傳入的 states 轉換成由 {key, val} 對象構成的數組,接着調用 forEach 方法遍歷這個數組,構造一個新的對象,這個新對象每個元素都返回一個新的函數 mappedState,函數對 val 的類型判斷,如果 val 是一個函數,則直接調用這個 val 函數,把當前 store 上的 state 和 getters 作為參數,返回值作為 mappedState 的返回值;否則直接把 this.$store.state[val] 作為 mappedState 的返回值。
那么為何 mapState 函數的返回值是這樣一個對象呢,因為 mapState 的作用是把全局的 state 和 getters 映射到當前組件的 computed 計算屬性中,我們知道在 Vue 中 每個計算屬性都是一個函數。
為了更加直觀地說明,回到剛才的例子:
import { mapState } from 'vuex' export default { // ... computed: mapState({ // 箭頭函數可以讓代碼非常簡潔 count: state => state.count, // 傳入字符串 'count' 等同於 `state => state.count` countAlias: 'count', // 想訪問局部狀態,就必須借助於一個普通函數,函數中使用 `this` 獲取局部狀態 countPlusLocalState (state) { return state.count + this.localCount } }) }
經過 mapState 函數調用后的結果,如下所示:
import { mapState } from 'vuex' export default { // ... computed: { count() { return this.$store.state.count }, countAlias() { return this.$store.state['count'] }, countPlusLocalState() { return this.$store.state.count + this.localCount } } }
我們再看一下 mapState 參數為數組的例子:
computed: mapState([ // 映射 this.count 到 this.$store.state.count 'count' ])
經過 mapState 函數調用后的結果,如下所示:
computed: { count() { return this.$store.state['count'] } }
.