輔助函數
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']
}
}
.
