Vuex的Module(哎,這個過重要了,不得不看啊)

化整爲零,按部就班

沒有模塊是不行的,就像沒有人可以一步搭成金字塔。bash

因爲使用單一狀態樹,應用的全部狀態會集中到一個比較大的對象。函數

當應用變得很是複雜時,你會發現你的Vuex模塊變成了一個即將上千行的大模塊。post

爲了解決以上問題,Vuex 容許咱們將 單個store 分割成模塊(module)。ui

每一個模塊擁有本身的 state、mutation、action、getter、甚至是嵌套子模塊(進行一樣方式的分割)this

const moduleA = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: () => ({ ... }),
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的狀態
store.state.b // -> moduleB 的狀態
複製代碼
  • 模塊的局部狀態

對於模塊內部的 mutation 和 getter,接收的第一個參數是本身所在的模塊對象。spa

const moduleA = {
  state: () => ({
    count: 0
  }),
  mutations: {
    increment (state) {
      // 這裏的 `state` 對象是本身所在的模塊對象
      state.count++
    }
  },
  getters: {
    doubleCount (state) {// 同上拉~
      return state.count * 2
    }
  }
}
複製代碼

模塊內部的 action稍有不一樣,還記得我曾經說過的context嘛?當時是讓讀者看成是本身所在的模塊對象去使用,其實並非,它擁有能夠訪問父節點狀態的屬性context.rootStatecode

const moduleA = {
  actions: {
    incrementIfOddOnRootSum ({ state, commit, rootState }) {
      if ((state.count + rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}
複製代碼

getter會在第三個參數內暴露出來cdn

const moduleA = {
  getters: {
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}
複製代碼
  • 命名空間 namespaced

默認狀況下,模塊內部的 action、mutation 和 getter 是註冊在全局命名空間的——這樣使得多個模塊可以對同一 mutation 或 action 做出響應。對象

你能夠經過添加 namespaced: true 的方式使其成爲帶命名空間的模塊(幾乎都是這麼作的)。blog

當模塊被註冊後,它的全部 getter、action 及 mutation 都會自動根據模塊註冊的路徑調整命名。例如:

const store = new Vuex.Store({
// 第一層嵌套
  modules: {
    account: {
      namespaced: true,

      // 模塊內容
      state: () => ({ ... }), // state原本就是嵌套的, `namespaced` 屬性對他無影響
      getters: {
        isAdmin () { ... } // -> getters['account/isAdmin'] 使用方法
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      // 第二層嵌套模塊
      modules: {
      //沒用namaspaced
        myPage: {
          state: () => ({ ... }),
          getters: {
            profile () { ... } // -> getters['account/profile'] // 因此實際上是和父親層級同樣的調用
          }
        },
        //用了namaspaced
        posts: {
          namespaced: true,
          state: () => ({ ... }),
          getters: {
            popular () { ... } // -> getters['account/posts/popular'] // 有本身的層級
          }
        }
      }
    }
  }
})
複製代碼
  • 命名空間怎麼訪問其餘 命名空間 或者 全局空間?

咱們能夠看到命名空間開啓後,嵌套模塊就像是「子組件」,那確定是有辦法讓他去訪問都父級模塊的。否則實用性幾乎就沒用了。

以前,也就是上面那個《模塊的局部狀態》章節稍微說了說怎麼去訪問(之說了state一些部分),如今開始詳細的解釋如下。

modules: {
  foo: {
    namespaced: true,// 記得開啓

    getters: {
      // 在這個模塊的 getter 中,`getters` 被局部化了
      // 你能夠看到第三個參數是rootState,第四個參數是rootGetters
      someGetter (state, getters, rootState, rootGetters) {
        getters.someOtherGetter // -> 'foo/someOtherGetter'
        rootGetters.someOtherGetter // -> 'someOtherGetter'
      },
      someOtherGetter: state => { ... }
    },

    actions: {
      // 在這個模塊中, dispatch 和 commit 也被局部化了
      // 他們能夠接受 `root` 屬性以訪問根 dispatch 或 commit
      someAction ({ dispatch, commit, getters, rootGetters }) {
        getters.someGetter // -> 'foo/someGetter'
        rootGetters.someGetter // -> 'someGetter'

        dispatch('someOtherAction') // -> 'foo/someOtherAction'
        dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'  null是參數,必須填,無參數就填空對象或者null
        
        // 從上面你能夠觀察到,其實它已是從父模塊觸發這個dispatch了,這就簡單了。
        // 父級怎麼觸發子級的就怎麼使用,就這樣兄弟模塊之間的交流就實現了。
        dispatch('someOtherAction/otherModule', null, { root: true }) // -> 'someOtherAction' 
        

        commit('someMutation') // -> 'foo/someMutation'
        commit('someMutation', null, { root: true }) // -> 'someMutation'
      },
      someOtherAction (ctx, payload) { ... }
    }
  }
}

複製代碼
  • 如何在局部模塊註冊全局action呢?

若須要在帶命名空間的模塊註冊全局 action,你可添加 root: true,並將這個 action 的定義放在函數 handler 中。例如:

{
  actions: {
    someOtherAction ({dispatch}) {
      dispatch('someAction')
    }
  },
  modules: {
    foo: {
      namespaced: true,
     
      actions: {
        someAction: { // 原本是一個函數,如今變成一個對象
          root: true,  // 必須未true才能註冊到全局
          handler (namespacedContext, payload) { ... } // -> 'someAction' // 必須handler名字的函數。,而後此函數與正常函數寫法一致。
        }
      }
    }
  }
}
複製代碼
  • 簡化輔助函數map...的寫法

computed: {
  ...mapState({
    a: state => state.some.nested.module.a,
    b: state => state.some.nested.module.b
  })
},
methods: {
  ...mapActions([
    'some/nested/module/foo', // -> this['some/nested/module/foo']()
    'some/nested/module/bar' // -> this['some/nested/module/bar']()
  ])
}

// 改寫爲
computed: {
  ...mapState('some/nested/module', {
    a: state => state.a,
    b: state => state.b
  })
},
methods: {
  ...mapActions('some/nested/module', [
    'foo', // -> this.foo()
    'bar' // -> this.bar()
  ])
}
複製代碼

還剩下一點內容我的以爲和入門無關,就不在贅述增長閱讀壓力,有興趣自行移步官網觀賞。

相關文章
相關標籤/搜索