最近nuxt.jsを触っていてvuexについて理解するまでちょっと時間がかかったので、ポイントを整理しておこうかと思います。

nuxt.jsでプロジェクトを作った場合、storeディレクトリがあるので、その下にindex.jsを作ってそこに記述していきます。

今回参考にしたサイトはこちら

コードはこんな感じです。

import _ from 'lodash'

// 状態の保存をしておく機能
export const state = () => ({
  todos: []
})

// stateから状態を取得する処理
export const getters = {
  todos_all: state => state.todos,
  todos: state => state.todos.filter(todo => todo.status === 'todo')
}

// stateを変更する変更
// 同期的に変更する
export const mutations = {
  addTodo(state, newTodo) {
    state.todos.push(newTodo)
  },
}

// ビューからのeventに反応してmutationsを発行する処理
// APIとの非同期処理もここで行う
export const actions = {
  async fetchTodos({ commit }) {
    await this.$axios.$get('/todos').then(res => {
      let todos = []
      if (_.has(res, 'documents')) {
        todos = res.documents.map(doc => {
          return {
            id: _.last(doc.name.split('/')),
            title: doc.fields.title.stringValue,
            status: doc.fields.status.stringValue
          }
        })
      }
      commit('updateTodos', todos)
    })
  },
  async addTodo({ commit }, payload) {
    const req = {
      fields: {
        title: {
          stringValue: payload.title
        },
        status: {
          stringValue: 'todo'
        }
      }
    }
    commit('addTodo', newTodo)
  }
}

ちなみに、上記の方法はモジュールモードで、クラシックモードという以下の書き方もあります。

const store = new Vuex.Store({
  state: {},
  getters:{},
  mutations: {},
  actions:{}
})

 

vuexで覚えるべきこと

vuexを使用する上で最初に覚えるべきことはstate、getters、mutations、actions、moduleの5つです。

state

画面に表示するデータを保存しておく機能です。

getters

stateに格納されているデータを取得する機能です。

一覧や詳細ページでデータを表示する際に呼び出されます。

mutations

stateを更新するモジュールのような機能です。

基本的に画面操作では呼び出されず、下のactionsから呼び出します。

ちなみにmutationsを呼び出す場合はcommit(mutation名)という形式になります。

actions

画面操作で呼び出されてAPIと非同期通信したりmutationsを呼び出したりします。

module

moduleは上の4つをまとめる機能です。機能が大きくなった時にストアを分けたい時に使います。

nuxt.jsでmoduleを使いたい場合はstoreディレクトリの下にindex.js以外のjsファイル(例:todos.js)を作成すると自動的にmoduleになるみたいです。

イメージ用のサンプルコードは以下になります。(参照元はこちら)

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

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

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

 

vuexの使い方

次にvuexを操作する画面を見てみます。

<template>
  <div>
    <ul>
      <li
        v-for="todo in todos"
        :key="todo.id">
        <span>{{ todo.title }}</span>
        <small 
          class="change-status" 
          @click="handleDoneTodo(todo)">
          done
        </small>
      </li>
    </ul>
  </div>
</template>

<script>
import { mapGetters, mapActions } from 'vuex'
import _ from 'lodash'

export default {
  computed: {
    ...mapGetters(['todos'])
  },
  methods: {
    async handleDoneTodo(todo) {
      const payload = _.cloneDeep(todo)
      payload.status = 'done'
      await this.updateTodo(payload)
    },
    ...mapActions(['updateTodo'])
  }
}
</script>

<style scoped>
.change-status {
  text-decoration: underline;
  cursor: pointer;
  text-indent: 1em;
}
</style>

vuexを使用する際はそのままgettersやactionsを呼び出すのではなく、vuexからmapGettersやmapActionsを使用します。

mapGetters等ヘルパーを使うのは複数のstateやgettersを宣言する際、毎回store.getters.getters名の様に記述するのは冗長なので、省略するために使うようです。

 

これぐらい理解できていたらひとまずOKでしょう。

カテゴリー: JavaScript

0件のコメント

コメントを残す

メールアドレスが公開されることはありません。