Vueコア技術-57,Vuex-コア概念-MOdule


一、前言
      Action,   vuex          
     Vuex        :Module

二、Vuex-Module
質問:
                 ,        ,store         

解決:
Vuex   store     
          state、mutation、action、getter、        ——             
// moduleA
const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

// moduleB
const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

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

store.state.a // -> moduleA    
store.state.b // -> moduleB    

三、モジュールの局部状態
1,モジュール内部のmutationとgetter,受信した最初のパラメータはモジュールの局所状態オブジェクトである.
// moduleA
const moduleA = {
  state: { count: 0 },
  mutations: {
    increment (state) {
      //     `state`           
      state.count++
    }
  },

  getters: {
    doubleCount (state) {
      return state.count * 2
    }
  }
}

2,モジュール内部のaction,局所状態はcontextを通過する.stateが露出するルートノードの状態はcontextである.rootState:
// moduleA
const moduleA = {
  actions: {
    // state     ,rootState      
    incrementIfOddOnRootSum ({ state, commit, rootState }) {
      if ((state.count + rootState.count) % 2 === 1) {
        commit('increment')
      }
    }
  }
}

3,モジュール内部のgetter,ルートノード状態が3番目のパラメータとして露出する.
// moduleA
const moduleA = {
  getters: {
    // rootState      
    sumWithRootCount (state, getters, rootState) {
      return state.count + rootState.count
    }
  }
}

四、ネーミングスペース
     ,     action,mutation getter           
              mutation   action     。

モジュールのカプセル化と多重性を向上させるには、namespaced:trueを追加してネーミングスペース付きモジュールにすることができます.モジュールが登録されると、すべてのgetter、action、mutationがモジュール登録のパスに基づいて自動的にネーミングを調整します.
例:
onst store = new Vuex.Store({
  modules: {
    account: {

      //       
      namespaced: true,

      //     (module assets)
      state: { ... }, //              ,   `namespaced`           
      getters: {
        isAdmin () { ... } // -> getters['account/isAdmin']
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      //     
      modules: {
        //           
        myPage: {
          state: { ... },
          getters: {
            profile () { ... } // -> getters['account/profile']
          }
        },

        //          
        posts: {
          namespaced: true,

          state: { ... },
          getters: {
            popular () { ... } // -> getters['account/posts/popular']
          }
        }
      }
    }
  }
})
        getter action       getter,dispatch commit
      (module assets) ,                  
  namespaced   ,           

ネームスペースのあるモジュール内でグローバルコンテンツにアクセス
         state getter,
rootState rootGetter            getter,
    context       action

              action   mutation,
 { root: true }        dispatch commit  
modules: {
  foo: {
    namespaced: true,

    getters: {
      //        getter  ,`getters`      
      //       getter           `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'

        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,
          handler (namespacedContext, payload) { ... } // -> 'someAction'
        }
      }
    }
  }
}

ネーミングスペース付きバインド関数
質問:
   mapState, mapGetters, mapActions mapMutations                ,
         :
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()
  ])
}

createNamespacedHelpersを使用して、指定したネーミングスペース値にバインドされた新しいコンポーネントバインドされた補助関数をオブジェクトに返すネーミングスペース補助関数を作成します.
import { createNamespacedHelpers } from 'vuex'

const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')

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

五、プラグイン開発者の注意事項
                     Vuex store,               

この場合、プラグインのパラメータオブジェクトでスペース名を指定できます.
//                
//      Vuex     
export function createPlugin (options = {}) {
  return function (store) {
    //                (type)  
    const namespace = options.namespace || ''
    store.dispatch(namespace + 'pluginAction')
  }
}

六、モジュール動的登録
storeの作成後にstoreを使用できます.registerModuleメソッド登録モジュール:
//      `myModule`
store.registerModule('myModule', {
  // ...
})
//        `nested/myModule`
store.registerModule(['nested', 'myModule'], {
  // ...
})


//        store.state.myModule store.state.nested.myModule       

モジュール動的登録機能により、他のVueプラグインがstoreに新しいモジュールを追加することでVuex管理状態を使用できるようにする
例:
vuex-router-sync               vue-router   vuex      ,           。

モジュールを動的にアンインストールするには:
     store.unregisterModule(moduleName)       
  ,             ,    store       

保留state:
     module ,        state(               state)

preserveStateオプションでアーカイブできます.
store.registerModule('a', module, { preserveState: true })

七、モジュール再利用
質問:
    store           
             ,              ,
           store              。

解決:
             (  2.3.0+   ):
const MyReusableModule = {
  state () {
    //         
    return {
      foo: 'bar'
    }
  },
  // mutation, action   getter   ...
}