LoginSignup
2
3

More than 3 years have passed since last update.

なるはや Vue SPA入門:Vuex モジュール

Last updated at Posted at 2019-08-04

Vue CLI3 で作成した SPA(Single Page Application)プロジェクト上で、段階的に Vue.js を学んで行きましょう。

目次はこちら

今回は Vuex モジュール編です。

前提事項

API コール編 が完了していること。

Vuex モジュール

アプリケーションの全ての状態は、一つの大きなストアオブジェクトに内包されます。しかしながら、アプリケーションが大きくなるにつれて、ストアオブジェクトは膨れ上がってきます。そのため Vuex ではストアをモジュールに分割できるようになっています。

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

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

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

store.state.a // -> `moduleA` のステート
store.state.b // -> `moduleB` のステート

counter モジュール

Vuex 編で作成したカウンターを Vuex のモジュールを使うよう修正します。

src/store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const counter = {
  namespaced: true, // モジュールの名前空間を有効にする

  state: {
    count: 0,
  },
  getters: {
    double(state) {
      return state.count * 2
    },
  },
  mutations: {
    increment(state) {
      state.count++
    },
    decrement(state) {
      state.count--
    },
  },
  actions: {
    increment(context) {
      context.commit('increment')
    },
    // 引数に ES2015 の引数分割束縛を使った例(context を省略できる)
    decrement({ commit }) {
      commit('decrement')
    },
  },
}

export default new Vuex.Store({
  modules: {
    counter: counter
  },
})

Counter.vue も修正します。

src/views/Counter.vue
export default {
  // ...
  computed: {
    // counter モジュールの state を参照する
    ...mapState({
      count: state => state.counter.count
    }),
    // counter モジュールの getter を名前空間を使用して参照する
    ...mapGetters({
      double: "counter/double"
    })
  },
  methods: {
    // counter モジュールの action を名前空間を使用して参照する
    ...mapActions({
      increment: "counter/increment",
      decrement: "counter/decrement"
    })
  }
};

todoList モジュール

コンポーネント編で作成した TODO List を Vuex のモジュール機能を使うよう修正します。

src/store.js
// ...

const counter = {
  // ...
}

const todoList = {
  namespaced: true, // モジュールの名前空間を有効にする

  state: {
    todos: [],
  },
  getters: {
    todos(state) {
      return state.todos
    }
  },
  mutations: {
    todos(state, todos) {
      state.todos = todos
    },
    remove(state, idToRemove) {
      state.todos = state.todos.filter(todo => {
        return todo.id !== idToRemove
      })
    }
  },
  actions: {
    getTodos({ commit }) {
      fetch('http://localhost:8080/todos.json')
        .then(response => response.json())
        .then(json => {
          console.log(json)
          commit('todos', json.todos)
        })
        .catch(error => console.error('Error:', error))
    }
  }
}

export default new Vuex.Store({
  modules: {
    counter: counter,
    todoList: todoList,
  },
})

TodoList.vue も修正します。

src/views/TodoList.vue
import TodoListItem from "../components/TodoListItem";
import TodoInputText from "../components/TodoInputText";
import { mapGetters } from "vuex";
import { mapMutations } from "vuex";
import { mapActions } from "vuex";

export default {
  components: {
    TodoListItem,
    TodoInputText
  },
  created() {
    this.getTodos();
  },
  computed: {
    ...mapGetters({
      todos: "todoList/todos"
    })
  },
  methods: {
    ...mapMutations({
      remove: "todoList/remove"
    }),
    ...mapActions({
      getTodos: "todoList/getTodos",
      add: "todoList/add"
    }),
    removeTodo(idToRemove) {
      this.remove(idToRemove);
    },
    addTodo(text) {
      this.add(text);
    }
  }
};

コンポーネント編の演習で TODO を追加できるようにした方は、それらの機能も Vuex のモジュールを使うよう修正してみてください。

動作確認

カウンター、TODO リストともに以前と同様に動くか確認してください。

次回

Vuex ファイル分割

2
3
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
2
3