Vuex + axiosでの基本的なAPI操作方法(CRUD)追加・削除・更新・フィルター
Vuex + axiosを使って、追加・削除・更新・フィルターといった基本的なAPI操作方法(CRUD)を紹介します。
Vuex + axiosでの基本的なAPI操作方法
vuexの基本的な使い方の通りにstoreフォルダの中にmodulesフォルダを作成し、その中にtodos.jsを作成します。
index.js
import Vuex from 'vuex'
import Vue from 'vue'
import todos from './modules/todos'
// Load Vuex
Vue.use(Vuex)
// Create store
export default new Vuex.Store({
modules: {
todos
}
})
todos.js
import axios from 'axios'
const state = {}
const getters = {}
const actions = {}
const mutations = {}
export default {
state,
getters,
actions,
mutations
}
axiosをインポートして、使うものを宣言してエクスポートしておきます。
あとはここに処理を記述していきます。
データの初期値を設定する
dataを管理するところなので、次のように記述します。
const state = {
todos: [],
}
変更があったときに再評価されるようにする
算出プロパティと同じように動くgettersを使ってデータに変更があった場合に再評価できるようにします。
const getters = {
allTodos: (state) => state.todos
}
コンポーネント
import {mapGetters } from 'vuex'
export default {
name: 'Todos',
computed: mapGetters(['allTodos']),
}
APIからデータを取得して表示する
actionsとmutationsを設定します。
データを取得するためのactions
const actions = {
// Set todo
async fetchTodos({ commit }) {
const response = await axios.get('https://....com/todos')
commit('setTodos', response.data);
},
...
}
actions→mutations→stateという流れを作ることで、actionsで複数のcommitを設定できます。
APIからデータを取得するにはactionsで非同期処理async-awaitを使います。
axiosでgetしたものをresponseに格納します。
コンソールなどでresponseの中身を確認します。
そしてデータに、response.dataなどとするとアクセスできることを確認したら、commitします。
データを取得するためのmutations
const mutations = {
// settodo
setTodos: (state, todos) => (state.todos = todos),
}
actionsで設定したオブジェクトにアクセスして、todosのデータをstate.todosに格納します。
コンポーネントで表示
そしてあとはtemplateタグで表示します。
<div class="todos">
<div
v-for="todo in allTodos"
:key="todo.id"
>
{{todo.title}}
</div>
</div>
データを使うには、mapGettersとmapActionsをインポートして設定しておく必要があります。
import {mapGetters, mapActions } from 'vuex'
export default {
...
methods: {
...mapActions(['fetchTodos']),
},
...
created () {
this.fetchTodos()
}
}
createdはVueインスタンスの作成が完了して、DOMがまだ作られていない状態であり、mountedではDOMが作成された直後の状態です。
createdの中でAPIなどの外部からのデータを受け取っても、dataオブジェクトはすでにリアクティブになっているのでcreated()を使います。
データを追加する
データを追加するためのactions
// Add todo
async addTodo({commit}, title) {
const response = await axios.post('https://....com/todos',
{ title, completed: false})
commit('newTodo', response.data)
},
追加するときは、postを使います。
そして、追加したいデータを第二引数にオブジェクトで設定します。
commit部分はfetchと大体同じです。
データを追加するためのmutations
// Addtodo
newTodo: (state, todo) => state.todos.unshift(todo),
todosの中に、新しいtodoをunshiftやpushすることで追加することができます。
コンポーネント
import {mapActions} from 'vuex'
export default {
name: 'AddTodo',
data() {
return {
title: '',
}
},
methods: {
...mapActions(['addTodo']),
onSubmit(e) {
e.preventDefault()
this.addTodo(this.title)
}
}
}
データを削除する
データを削除するためのactions
// delete todo
async deleteTodo({commit}, id) {
await axios.delete(`https://....com/todos/${id}`);
commit('removeTodo', id);
},
削除には、deleteを使います。
よくidを渡してそれを削除するという方法が使われます。
データを削除するためのmutations
// deletetodo
removeTodo: (state, id) => state.todos = state.todos.filter(todo => todo.id !== id),
filter()を使って、idが一致するもの以外の配列を取得することで、そのidの入っていない配列を作成(削除)することができます。
コンポーネント
methods: {
...mapActions(['fetchTodos', 'deleteTodo']),
...
},
methodsのなかのmapActionsに作成したdeleteTodoを追加することで使えるようになります。
<button class="delete" @click="deleteTodo(todo.id)">削除</button>
データをフィルターする
データをフィルターするためののactions
// Filter todo
async filterTodos( {commit}, e) {
// Get selected numver
const limit = parseInt(e.target.options[e.target.options.selectedIndex].innerText)
const response = await axios.get(`https://....com/todos?_limit=${limit}`);
commit('setTodos', response.data);
},
上は表示数でフィルターする場合です。
limitなどでurlに受け取る数字を格納できる変数を作成します。
selectのoptionタグなどの数字を取得して使いたい場合は、上のようにJavaScriptを記述入します。
なおmutationsは不要となります。
コンポーネント
<select @change="filterTodos($event)">
<option value="100">100</option>
<option value="50">50</option>
<option value="20">20</option>
</select>
このようにoptionのinnnterTextを取得できるように記述します。
methods: mapActions(['filterTodos'])
忘れずにscriptタグにmapActionsを追加します。
データをアップデートする
データをアップデートするためのactions
// update todo
async updateTodo({commit}, updTodo) {
const response = await axios.put(`https://....com/todos/${updTodo.id}`, updTodo);
commit('updateTodo', response.data)
}
データの更新にはputを使います。
アップデートするidを設定して、第二引数でtodoを渡します。
データをアップデートするためのmutations
// updatetodo
updateTodo: (state, updTodo) => {
const index = state.todos.findIndex(todo => todo.id === updTodo.id);
if (index !== -1) {
state.todos.splice(index, 1, updTodo);
}
データを更新するためには、まずidを探します。
todoの中のidと更新したいもののidが一致するものと指定したい場合、
find()やfindIndex()を使います。
条件を満たす要素がない場合、-1を返すので、-1でない場合のみ、処理できるようにif文を設定します。
使い分けは、JavaScriptの配列メソッド、どれを使えばいいのか?を参考にしてみてください。
コンポーネント
methods: {
...mapActions(['fetchTodos', 'deleteTodo', 'updateTodo']),
// Update todo
onDblClick(todo) {
const updTodo = {
id: todo.id,
title: todo.title,
completed: !todo.completed
}
this.updateTodo(updTodo)
}
},
忘れずにmapActionsに追加します。
上の例ではダブルクリックしたらcompeltedだけがトグルします。