vuex 源碼:深入 vuex 之輔助函數 mapState


https://juejin.im/post/5ae433ab518825671a6388d5

准備

解讀前,我們需要熟悉一些方法的使用:

解讀

先來 mapState 的使用方式:

import { mapState } from 'vuex' export default { computed: mapState([ // 映射 this.count 為 store.state.count 'count' ]) } 復制代碼

mapState 返回一個對象,我們知道以上的代碼最后會變成這樣:

import { mapState } from 'vuex' export default { computed: { count () { return this.$store.state.count } } } 復制代碼

那么我們就來開始看看 mapState 做了什么處理。

還是從 vuex 的 APi 看起,打開 src/index.js 文件,最下面的代碼中可以看到 vuex 暴露出的 mapState:

export default { Store, install, mapState, mapMutations, mapGetters, mapActions } 復制代碼

定位后可以找到最前面的引入:

import { mapState, mapMutations, mapGetters, mapActions } from './helpers' 復制代碼

打開 src/helpers.js 文件,里面便有 mapState 的實現。

normalizeMap

想知道 mapStat 這個方法的實現,還得知道里面的 normalizeMap 這個方法的實現。定位找到 normalizeMap 方法:

function normalizeMap (map) { return Array.isArray(map) ? map.map(key => ({ key, val: key })) : Object.keys(map).map(key => ({ key, val: map[key] })) } 復制代碼

這個方法主要是格式化 mapState 傳進來的 states 參數。我們會知道 states 參數會是兩種形式,一種是以數組的方式傳入,另一種則是以對象的方法傳入。

例如以下代碼:

// 以數組的方式傳入 mapState([ 'count', 'add' ]) // 以對象的方法傳入 mapState({ count: state => state.count, countAlias: 'count' }) 復制代碼

經過 normalizeMap 方法處理后會變成這樣:

// 以數組的方式傳入 [ { key: 'count', val: 'count' }, { key: 'add', val: 'add' } ] // 以對象的方法傳入 [ { key: count, val: state => state.count }, { key: countAlias, val: 'count' } ] 復制代碼

mapState

知道了 normalizeMap 方法的實現,再回頭看 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 格式化后返回的數組進行遍歷,拼接一個符合 computed 的對象(需有返回值)。

對 normalizeMap 返回數組的對象里的 val 有兩個判斷。如果不是函數,直接查找 this.$store.state[val] 返回 state。如果是函數,則需要使用 call 將 val 這個函數的 this 指向 vue 實例,然后將 state 和 getters 傳入,最后執行 val 函數。

val 函數

如果 val 是函數,可能有點難理解,舉個例子,傳入的參數可能是這樣子的:

computed: mapState({
  countPlusLocalState (state) {
    return state.count + this.localCount } }) 復制代碼

經過 normalizeMap 方法后返回的對象為:

[
  {
    key: 'countPlusLocalState', val: function (state) { return state.count + this.localCount } } ] 復制代碼

再經過 mapState 最后返回的 res 是。這里會將 val 函數執行一遍,將函數的返回值 return 出來。

{
  countPlusLocalState: function mappedState () { return this.$store.state.count + this.localCount } } 復制代碼

至此,mapState 的解讀已經結束了。另外,mapState 還經常使用到 es6 的擴展運算符,這個不是 vuex 的實現,而是 es6 的一個新特性:

computed: {
  localComputed () { /* ... */ }, // 使用對象展開運算符將此對象混入到外部對象中 ...mapState({ // ... }) } 復制代碼

例外需要注意,如果要使用 es6 的擴展運算符,還需要引入一個 babel 包:babel-plugin-transform-object-rest-spread

總結

mapState 的代碼不多,主要的功能就是將傳入的數組或對象轉成 computed 計算屬性能夠識別的代碼。比較難理解的就是對象帶有函數的返回值有點繞,多看幾遍理解理解。

mapState 里面的代碼實現非常的簡潔精湛,主要用到了 js 的一些內置函數做處理,如果是我,估計會一直寫 for 循環實現吧哈哈,從中收獲到不少知識的。至此,vuex 的解讀算告一段落。


作者:cobish
鏈接:https://juejin.im/post/5ae433ab518825671a6388d5
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM