ブログの投稿ログ

2021年
9月
8月
7月
6月

VueXでTodoアプリ 完

前回に引き続きVuexを使用したToDoアプリの作成をしていきたいと思います。

今回の実装内容

  • 完了リストへ移動
  • 完了リストから未完了への移動
  • 削除機能
  • LocalStorageへの保持

今日のコード

codesandbox


vue側追加項目


<template>
......

    <div class="wrap">
      <h2>リスト</h2>
      <ul>
        // todoListをfor分で回す
        <li v-for="(item, key) in todoList" :key="key">
          <p>id: {{item.id}}</p>
          <p>text: {{item.text}}</p>
          // 完了へ移動させる為のクリックイベント
          <button @click="doneTodo(item.id)">Done</button>
        </li>
      </ul>
    </div>
    <div class="wrap">
      <h2>完了</h2>
      <ul>
        <li v-for="(item, key) in todoDone" :key="key">
          <p>id: {{item.id}}</p>
          <p>text: {{item.text}}</p>
          // 未完了へ移動させる為のクリックイベント
          <button @click="resetTodo(item.id)">Reset</button>
          // 削除させる為のクリックイベント
          <button @click="deleteTodo(item.id)">Delete</button>
        </li>
      </ul>
    </div>
  </div>
</template>

...........
...........
    doneTodo: function(id) {
      this.$store.dispatch('done', {
        id: id
      })
    },
    resetTodo: function(id) {
      this.$store.dispatch('reset', {
        id: id
      })
    },    
    deleteTodo: function(id){
      this.$store.dispatch('delete', {
      id: id
      })
    }
  }
}
</script>

まず、v-forでtodoListの配列を回しています。
この際、keyを設定しないと各追加項目を識別できなくなってしまうため、Vue側のエラーとなって出てきてしまうので注意しましょう。
doneTodo,resetTodo,deleteTodoのクリックイベントにはidを引数として持ちstoreへディスパッチしています。

store側追加項目

import Vue from "vue";
import Vuex from "vuex";

// storageへ保持する為のプラグインをインポート
import createPersistedState from "vuex-persistedstate";

Vue.use(Vuex);

const store = new Vuex.Store({

// storageへ保持する宣言
  modules: {},
  plugins: [createPersistedState()],

  state: {
    todoList: [],
    todoDone: []
  },

  actions: {
    addTodo(context, todo) {
      context.commit("ADD_TODO", todo.text);
    },
    // クリックイベントdoneTodoのディスパッチを受け取る
    done(context, todo) {
      context.commit("Done_Todo", todo.id);
    },
    // クリックイベントresetTodoのディスパッチを受け取る
    reset(context, todo) {
      context.commit("RESET_TODO", todo.id);
    },
    // クリックイベントdeleteTodoのディスパッチを受け取る
    delete(context, todo) {
      context.commit("DELETE_TODO", todo.id);
    }
  },

  mutations: {
    ADD_TODO(state, text) {
      const todo = {
        id: 0,
        text: text
      };
      if (state.todoList.length !== 0) {
        todo.id = state.todoList[state.todoList.length - 1].id + 1;
      }
      state.todoList.push(todo);
    },
    // actionから受け取ったコミットにロジックを書いていく
    Done_Todo(state, id) {
      // stateで定義したtodoListを回していく
      for (let i = 0; i < state.todoList.length; i++) {
        // もしidが配列の中のidと一致したら実行
        if (state.todoList[i].id === id) {
          // stateのtudoDoneの配列にプッシュ
          state.todoDone.push(state.todoList[i]);
          // ターゲットをtodoListから削除
          state.todoList.splice(i, 1);
          break;
        }
      }
    },
    // actionから受け取ったコミットにロジックを書いていく
    RESET_TODO(state, id) {
      // 空のオブジェクトを定義
      var todo = {};
      // stateで定義したtodoListを回していく
      for (var i = 0; i < state.todoDone.length; i++) {
        // もしidが配列の中のidと一致したら実行
        if (state.todoDone[i].id === id) {
          // 上で定義したオブジェクトへターゲットを代入
          todo = state.todoDone[i];
          // ターゲットをtodoDoneから削除
          state.todoDone.splice(i, 1);
          break;
        }
      }
      // ターゲットが格納されたオブジェクトをtodoListへプッシュ
      state.todoList.push(todo);
      // todoListをソート
      state.todoList.sort((a, b) => {
        if (a.id < b.id) return -1;
        if (a.id > b.id) return 1;
        return 0;
      });
    },
    // actionから受け取ったコミットにロジックを書いていく
    DELETE_TODO(state, id) {
      // stateで定義したtodoListを回していく
      for (var i = 0; i < state.todoDone.length; i++) {
        // ターゲットを削除
        if (state.todoDone[i].id === id) {
          state.todoDone.splice(i, 1);
        }
      }
    }
  }
});

export default store;


以上になります。