vuex
提供了四個經常使用的輔助函數vue
mapState(namespace?: string, map: Array<string> | Object<string | function>): Object
vuex
computed: mapState({
// 箭頭函數可以使代碼更簡練
count: state => state.count,
// 傳字符串參數 'count' 等同於 `state => state.count`
countAlias: 'count',
// 爲了可以使用 `this` 獲取局部狀態,必須使用常規函數
countPlusLocalState (state) {
return state.count + this.localCount
}
})
複製代碼
看下源代碼(vuex\src\helpers.js
):數組
export const mapState = normalizeNamespace((namespace, states) => {
const res = {}
normalizeMap(states).forEach(({ key, val }) => {
res[key] = function mappedState () {
let state = this.$store.state
let getters = this.$store.getters
if (namespace) {
const module = getModuleByNamespace(this.$store, 'mapState', namespace)
if (!module) {
return
}
state = module.context.state
getters = module.context.getters
}
return typeof val === 'function'
? val.call(this, state, getters)
: state[val]
}
// mark vuex getter for devtools
res[key].vuex = true
})
return res
})
function normalizeNamespace (fn) {
return (namespace, map) => {
if (typeof namespace !== 'string') {
map = namespace
namespace = ''
} else if (namespace.charAt(namespace.length - 1) !== '/') {
namespace += '/'
}
return fn(namespace, map)
}
}
function normalizeMap (map) {
if (!isValidMap(map)) {
return []
}
return Array.isArray(map)
? map.map(key => ({ key, val: key }))
: Object.keys(map).map(key => ({ key, val: map[key] }))
}
複製代碼
mapState
是經過normalizeNamespace
返回的函數,他接收了參數:namespace
,map
,namespace
是命名空間,map
是具體的對象,其實按照官網說明namespace
是能夠不傳入的.而調用了normalizeNamespace
以後,就是將map
做爲state
傳入,而後調用normalizeMap
,將map
變成以{key,val:key}
這樣的格式的數組。構建完成以後。執行循環,而後將key
,以及val
爲mappedState
做爲value
存入到res
中markdown
res[key] = function mappedState () {
let state = this.$store.state
let getters = this.$store.getters
if (namespace) {
const module = getModuleByNamespace(this.$store, 'mapState', namespace)
if (!module) {
return
}
state = module.context.state
getters = module.context.getters
}
return typeof val === 'function'
? val.call(this, state, getters)
: state[val]
}
複製代碼
首先獲取了$store.state
和$store.getters
app
若是命名空間的時候函數
而後根據命名空間名,獲取了模塊,獲取模塊對應的state
和getters
。而後經過判斷咱們書寫的mapState
的第二個參數,是函數的話,就執行這個函數,將state
和getters
傳入,反之就返回state[val]
this
實例:spa
// 基於屬性的訪問
mapState({
searchInput: state => state.yourModuleName.searchInput,
})
// 使用namespace訪問
...mapState('yourModuleName',[
'searchInput',
])
複製代碼
mapGetters(namespace?: string, map: Array<string> | Object<string>): Object
爲組件建立計算屬性以返回 getter 的返回值。 第一個參數是可選的,能夠是一個命名空間字符串code
官方實例:orm
// map爲Array
computed: {
// 使用對象展開運算符將 getter 混入 computed 對象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
// map爲Object
...mapGetters({
// 把 `this.doneCount` 映射爲 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
複製代碼
看一下源碼實現
export const mapGetters = normalizeNamespace((namespace, getters) => {
const res = {}
normalizeMap(getters).forEach(({ key, val }) => {
// The namespace has been mutated by normalizeNamespace
val = namespace + val
res[key] = function mappedGetter () {
if (namespace && !getModuleByNamespace(this.$store, 'mapGetters', namespace)) {
return
}
return this.$store.getters[val]
}
// mark vuex getter for devtools
res[key].vuex = true
})
return res
})
複製代碼
和mapState
不一樣的地方是mapGetters
採用的是在this.$store.getters
取得值
示例:
methods: {
...mapMutations([
'increment', // 將 `this.increment()` 映射爲 `this.$store.commit('increment')`
// `mapMutations` 也支持載荷:
'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
account: (commit, account) => {
commit("account", account)
},
}),
...mapMutations({
add: 'increment' // 將 `this.add()` 映射爲 `this.$store.commit('increment')`
})
}
複製代碼
mapMutations(namespace?: string, map: Array<string> | Object<string | function>): Object
export const mapMutations = normalizeNamespace((namespace, mutations) => {
const res = {}
normalizeMap(mutations).forEach(({ key, val }) => {
res[key] = function mappedMutation (...args) {
// Get the commit method from store
let commit = this.$store.commit
if (namespace) {
const module = getModuleByNamespace(this.$store, 'mapMutations', namespace)
if (!module) {
return
}
commit = module.context.commit
}
return typeof val === 'function'
? val.apply(this, [commit].concat(args))
: commit.apply(this.$store, [val].concat(args))
}
})
return res
})
複製代碼
mutaions
獲取到{key,val:key}
相似於這樣得格式得數組,進行循環this.$store
獲取到commit
這個方法,若是是一個命名空間的module
,那麼就會經過getModuleByNamespace
獲取對應的module
store
內的commit
val
是function
(示例第二種狀況),傳入的是 2 個值,一個commit
,一個爲參數
,因此這就是爲何能獲取到commit
同時將本身的載荷payload
傳入的緣由function
那麼走的就是commit.apply(this.$store, [val].concat(args))
,而後提交改變了state
示例:
// Array
...mapActions([
'increment', // 將 `this.increment()` 映射爲 `this.$store.dispatch('increment')`
// `mapActions` 也支持載荷:
'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.dispatch('incrementBy', amount)`
]),
// Object
...mapActions({
add: 'increment' // 將 `this.add()` 映射爲 `this.$store.dispatch('increment')`
})
複製代碼
看下源碼實現:
export const mapActions = normalizeNamespace((namespace, actions) => {
const res = {}
normalizeMap(actions).forEach(({ key, val }) => {
res[key] = function mappedAction (...args) {
// get dispatch function from store
let dispatch = this.$store.dispatch
if (namespace) {
const module = getModuleByNamespace(this.$store, 'mapActions', namespace)
if (!module) {
return
}
dispatch = module.context.dispatch
}
return typeof val === 'function'
? val.apply(this, [dispatch].concat(args))
: dispatch.apply(this.$store, [val].concat(args))
}
})
return res
})
複製代碼
actions
是用來派發mutations
的,因此確定是須要一個dispatch
,能夠來自於根也能夠是子模塊mutation
是同樣的,也是分爲fun
和其餘類型,做爲處理