nuxtjsでVuexストアを使う

APIで取得したデータをpageのdataから[Vuexのストア](https://vuex.vuejs.org/ja/guide/)で管理してみる。

# ストアを作る

store/index.jsにstate, getters, mutationsを追加する。

stateは**データを格納する変数**を記述
gettersは**stateの情報を取得する関数**を記述
mutationsは**stateを操作する関数**を記述
actionsは**非同期のapi呼び出しとmutationのcommitをする関数**を記述

```javascript:store/index.js
export const state = () => ({
  messages: []
})

export const getters = {
  getShortMsgs: state => {
    return state.messages.filter(obj => obj.message.length < 10)
  }
}

export const mutations = {
  setMessages(state, messages) {
    state.messages = messages
  }
}

export const actions = {
  async takeMessages({ commit }, { limit }) {
    const { data } = await this.$axios.get(`http://localhost:3000/api?limit=${limit}`)
    commit('setMessages', data.data)
  }
}
```

# ストアを使う

## ストアに保存する(fetch + mutations)

apiからデータを取得して、mutationsのsetMessages関数でストアに保存する。
**`store.commit('関数名', 引数)`**

```vue:pages/index.vue
<template>
  <div>
  </div>
</template>

<script>
export default {
  async fetch({ $axios, store }) {
    const response = await $axios.get('http://localhost:3000/api?limit=10')
    store.commit('setMessages', response.data.data)
  }
}
</script>
```

### ストアをmessage.jsで作った場合

ストアのファイル名をmutationsの関数名の前に記述する。
**`store.commit('ファイル名/関数名', 引数)`**

```vue:pages/index.vue
<script>
export default {
  async fetch({ $axios, store }) {
    const response = await $axios.get('http://localhost:3000/api?limit=10')
    store.commit('message/setMessages', response.data.data)
  }
}
</script>
```

## ストアに保存する(actions)

actionsのtakeMessages関数でデータを取得してストアに保存する。
**`this.$store.dispatch('関数名', 引数)`**

```vue:pages/index.vue
<script>
export default {
  methods: {
    async loadMessages() {
      await this.$store.dispatch('takeMessages', { limit: 10 })
    }
  }
}
</script>
```

### ストアをmessage.jsで作った場合

ストアのファイル名をactionsの関数名の前に記述する。
**`this.$store.dispatch('ファイル名/関数名', 引数)`**

```vue:pages/index.vue
<script>
export default {
  methods: {
    async loadMessages() {
      await this.$store.dispatch('message/takeMessages', { limit: 10 })
    }
  }
}
</script>
```

## ストアのデータを取得する

stateのmessages変数を参照する
**`this.$store.state.変数名`**

gettersのgetShortMsgs関数で取得する
**`this.$store.getters.関数名`**

```vue:pages/index.vue
<template>
  <div>
    <ul>
      <li v-for="(obj, index) in messages" :key="index">
        {{ obj.message }}
      </li>
    </ul>
    <ul>
      <li v-for="(obj, index) in shortMsgs" :key="index">
        {{ obj.message }}
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  created() {
    this.loadMessages()
  },
  computed: {
    messages() {
      return this.$store.state.messages
    },
    shortMsgs() {
      return this.$store.getters.getShortMsgs
    }
  },
  methods: {
    async loadMessages() {
      await this.$store.dispatch('takeMessages', { limit: 10 })
    }
  }
}
</script>
```

### ストアをmessage.jsで作った場合

ストアのファイル名を変数名、関数名の前に記述する。
stateの変数
**`this.$store.state.ファイル名.変数名`**

gettersの関数
**`this.$store.getters['ファイル名/関数名']`**

```vue:index.vue
<script>
export default {
  computed: {
    messages() {
      return this.$store.state.message.messages
    }
    shortMsgs() {
      return this.$store.getters['message/getShortMsgs']
    }
  }
}
</script>
```

## ヘルパーを使う

`mapState`, `mapGetters`, `mapMutations`, `mapActions`をインポートする。
**`import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'`**

ヘルパーのオブジェクトを取得する。
state
**`...mapState(['変数名'])`**

getter
**`...mapGetters(['関数名'])`**

mutation
**`...mapMutations(['関数名'])`**

action
**`...mapActions(['関数名'])`**

ヘルパーのオブジェクトで参照する。
state変数
`this.$store.state.変数名`が`this.変数名`

getter関数
`this.$store.getters.関数名`が`this.関数名`

mutation関数
`this.$store.commit('関数名', 引数)`が`this.関数名(引数)`

action関数
`this.$store.dispatch('関数名', 引数)`が`this.関数名(引数)`

```vue:pages/index.vue
<template>
  <div>
    <ul>
      <li v-for="(obj, index) in messages" :key="index">
        {{ obj.message }}
      </li>
    </ul>
    <ul>
      <li v-for="(obj, index) in shortMsgs" :key="index">
        {{ obj.message }}
      </li>
    </ul>
    <button @click="moreMessages">もっと見る</button>
  </div>
</template>

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

export default {
  computed: {
    ...mapState(['messages']),
    ...mapGetters({
      shortMsgs: 'getShortMsgs'
    })
  },
  created() {
    this.loadMessages()
  },
  methods: {
    ...mapMutations(['setMessages']),
    ...mapActions(['takeMessages']),
    async moreMessages() {
      const { data } = await this.$axios.get('http://localhost:3000/api?limit=20')
      this.setMessages(data.data)
    },
    async loadMessages() {
      await this.takeMessages({ limit: 10 })
    }
  }
}
</script>
```

### ストアをmessage.jsで作った場合

ストアのファイル名をオブジェクト取得の第一引数に記述する。
state
**`...mapState('ファイル名', ['変数名'])`**

getter
**`...mapGetters('ファイル名', ['関数名'])`**

mutation
**`...mapMutations('ファイル名', ['関数名'])`**

action
**`...mapActions('ファイル名', ['関数名'])`**

```vue:pages/index.vue
<script>
export default {
  computed: {
    ...mapState('message', ['messages']),
    ...mapGetters('message', {
      shortMsgs: 'getShortMsgs'
    })
  },
  methods: {
    ...mapMutations('message', ['setMessages']),
    ...mapActions('message', ['takeMessages'])
  }
}
</script>
```