LoginSignup
47
35

More than 5 years have passed since last update.

【Nuxt.js】VuexモジュールモードでStore以下のファイル群を整理する時のあれこれ

Last updated at Posted at 2019-04-06

はじめに

Nuxt.jsのVuexモジュールモードで、store以下のファイルが増えてきて整理したくなりました。
いざディレクトリを切ってファイルを整理し始めると、stateやactionへのアクセス仕方で少し手間取ったので...

今回は、store配下でディレクトリを切った時、名前空間の違うvuexモジュールやVueコンポーネントからVuexのモジュールにアクセスする方法を備忘録的にまめておきます。

store内の構成

例として以下のようなディレクトリ構成下で説明して行きます。(コードの中身に意味はないでスルーしてください
ちなみにNuxt.jsではstore/index.jsがストアインスタンスを返さない時、モジュールモードになります。詳しくはこちら

store/
  ┣ shared/
    ┣ auth.js
  ┣ pages/
    ┣ mypage.js
pages/
  ┣ mypage/
    ┣ index.vue
store/models/auth.js
export const state = () => ({
 token: null
})

export const mutations = {
  setToken(state, token) {
    state.token = token
  }
}

export const actions = {
  setToken({ commit }, token) {
    commit('setToken', token)
  },
  deleteToken({ commit }) {
    commit('setToken', null)
  }
}
store/pages/mypage.js
export const state = () => ({
  name: ''
})

export const mutations = {
  setName(state, name) {
    state.name = name
  }
}

export const actions = {
  login({ dispatch }, name) {
    dispatch('setName', name)
    dispatch('shared/auth/setToken', 'dummy', { root: true })
  },
  logout({ dispatch }) {
    dispatch('setName', '')
    dispatch('shared/auth/deleteToken', null, { root: true })
  },
  setName({ commit }, name) {
    commit('setName', name)
  }
}
pages/mypage/index.vue
<template>
  <section>
    <p>{{ name }}</p>
    <p>{{ this.$store.state.pages.mypage.name }}</p>
    <p @click="login('Alis')">login</p>
    <p @click="logout">logout</p>
  </section>
</template>

<script>
import { mapState, mapActions } from 'vuex'

export default {
  computed: {
    ...mapState('pages/mypage', ['name'])
  },
  methods: {
    ...mapActions('pages/mypage/', [
       'login',
       'logout'
    ])
  }
}
</script>

では細かく見ていきましょう。

名前空間の違うVuexモジュールにアクセスする

今回の例で言うとstore/pages/mypage.jsからstore/models/auth.jsを参照したい時は以下のような形でauthモジュールのアクションを呼び出せます。

dispatch('shared/auth/setToken', 'dummy', { root: true })
dispatch('shared/auth/deleteToken', null, { root: true })

ここで2つのミソがあります。

1つ目はモジュール内は相対パス扱いなので{ root => true }第3引数のオプションに渡さないとpages/mypage/shared/auth/...を参照しに行ってエラーになります。

2つ目はshared/auth/deleteTokenのように引数を受け取らないactionを呼ぶ場合は第2引数をnull埋めしないと{ root => true }が効かずactionが呼ばれません。
これはエラーにならないので意外と気づかないです...

ComponentからVuexモジュールにアクセスする

stateの参照

stateにアクセスする時は直接参照するか、バインディングヘルパーを使う方法があります。

直接参照は$storeオブジェクトを掘っていくことで参照できます。

this.$store.state.pages.mypage.name

バインディングヘルパーを使う場合は...mapStateを使い、storeからの相対パスでnamespaceを指定します。

<template>
 <p>{{ name }}</p>
</template>

<script>
import { mapState } from 'vuex'

export default {
  computed: {
    ...mapState('pages/mypage', ['name'])
  }
}

ちなみにayncdata()からはcontextにstoreオブジェクトがあるのでそれを使って参照出来ます。

asyncData({ store }) {
  store.state.shared.auth.token
}

アクションの参照

アクションもバイディングヘルパーを使えばstateと同じように参照できます。
ちなみにバインディングヘルパーは以下のような感じで複数のvuexモジュールを指定する事も出来ます。

<template>
  <div>
   <p @click="login('Alis')">login</p>
   <p @click="deleteToken">logout</p>
 </div>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  methods: {
    ...mapActions('pages/mypage', [
       'login'
    ])
    ...mapActions('shared/auth', [
       'deleteToken'
    ])
  }

バリンティングヘルパーを使わない場合は以下の通りです。

export default {
  methods: {
    logout() {
       this.$store.dispatch('pages/mypage/logout')
     }
  }
}

まとめ

これでstore以下をディレクトリ切って整理出来ました。

47
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
35