Help us understand the problem. What is going on with this article?

Vuexの構造を超簡単にnamespace(名前空間)分割する

@nekobato さんの構造の複雑さとVuex書き分けという記事の中で複雑化したVuex構造を名前空間によって分割する手法が紹介されていましたが、名前空間分割にVuex公式が神対応してたため記事に起こしました。

TL;DR

Vuex 2.1より、Storeをモジュール分割する際にnamespaced: trueというオプションを追加することで、自動的に名前空間を付与することが出来るようになりました。
これによりtype.jsファイル等の名前空間手動管理地獄から開放されます!

※公式リファレンス

名前空間の分割 (Vuex 2.1以前)

(もう使わないと思うので折りたたみました)

(構造の複雑さとVuex書き分けより抜粋)
モジュールごとにnamespaceプレフィックスを作成し、type.jsファイルで管理する手法です。

modules/hello/type.js
const namespace = 'hello/'
export const HELLO  = namespace + 'HELLO'
export const SAY_HELLO   = namespace + 'SAY_HELLO'
export const TOGGLE_DONE = namespace + 'TOGGLE_DONE'
modules/hello/index.js
import * as types from './types'

export default helloModule = {
  state: {
    hello: false,
  },
  getters: {
    [types.HELLO] (state) {
      return state.hello
    }
  },
  actions: {
    [types.SAY_HELLO] (context, payload) {
      api.sayHello()
        .then((data) => {})
        .catch((err) => {})
    }
  },
  mutations: {
    [types.HELLO] (state, payload) {
      state.hello = true
    }
  }
}

名前空間を分割することでより安全にアプリを成長させていけるようになりますが、typeの管理が辛いです…
react+reduxの(おお神よ…我らをビジネスロジックに集中させ給え…)感が再来していますね。
加えて、人によってはメソッド名がなんかキモいと感じるかもしれません。

名前空間の分割 (Vuex 2.1以降)

namespacedというオプションを追加するだけでよくなりました!!!
このオプションを付けることで、state, getters, actions, mutationsには自動的に自分が属しているmodule名(この場合helloModule)と同名のnamespaceが付与されます。

modules/hello/index.js
// import * as types from './types' // 消滅

export default helloModule = {
  namespaced: true, // 追加
  state: {
    hello: false,
  },
  getters: {
    // 素直なメソッド名
    hello(state) {
      return state.hello
    }
  },
  actions: {
    // 素直なメソッド名
    sayHello(context, payload) {
      api.sayHello()
        .then((data) => {})
        .catch((err) => {})
    }
  },
  mutations: {
    // 素直なメソッド名
    hello(state, payload) {
      state.hello = true
    }
  }
}

呼び出すときは「mapState/mapActionsに引数で名前空間を渡す」「名前空間を明示的に指定する」のどちらのパターンでもOKです。
追記: mapStateの書き方はVuex:mapStateの書き方8パターン+11サンプルコードで詳しく扱われていたので、そちらも参考にしてみて下さい。Stateに限らずmapXxx系全般で使用できる知識です。

呼び出し側: 引数で名前空間を渡すパターン

computed: {
  ...mapState('helloModule', // ←名前空間を引数に渡す
    // ここのstateはルートのstateではなく、自動的に名前空間が認識されてhelloModule/stateになっている
    {  
      hello: state => state.hello
    }
  }
},
methods: {
  ...mapActions('helloModule', // ←名前空間を引数に渡す
    // this.sayHello() を this.$store.dispatch('helloModule/sayHello')にマッピング
    ['sayHello']
  )
}

呼び出し側: 名前空間を明示的に指定するパターン

computed: {
  ...mapState({
    hello: state => state.helloModule.hello // このstateはグローバル。名前空間を掘る。
  }
},
methods: {
  ...mapActions([
    // this.sayHello() を this.$store.dispatch('helloModule/sayHello')にマッピング
    'helloModule/sayHello'
  ])
}
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away