質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.19%

mountedをvuex化したい。

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 481

MasatofromMGSV

score 17

 環境

windows10(64) 
"vue": "^2.6.10",
"vuetify": "^2.1.0",
"vue-cli":"3.11.0",
"node":"v11.13.0"
プログラミング歴 5か月ほど

 やりたいこと

vuetify+vue-cliでtodoアプリ(講義さぼり回数カウントアプリ)を作っています。
授業名を入力してEnterを押すことで、欠席回数をカウントできるリストが出力されます。
下記URLです↓
https://vuejs-http-e3587.firebaseapp.com/
もちろんjsのlocalStorageという機能を使ってカウントもメモも永続化しています。
今まで、vuexを使っていなかったのでこれらをvuexに書き変えようとしました。

vuexに書き変えていない正常に動くブランチのソースコード

Count.vue

<template>
  <v-app>
    <v-content>
      <v-container>
        <v-row>
          <v-col cols="6">
            <v-text-field v-model="name" label="授業名" @keyup.enter="addTodo" required></v-text-field>
          </v-col>
        </v-row>
        <div v-for="(todo,index) in todos" :key="todo.name">
          <v-card card_id max-width="344" class="mx-auto">
            <v-card-title>{{todo.name}}</v-card-title>
            <v-card-text>
              <v-text-field label="メモ" v-model="todo.memo" @input="addMemo"></v-text-field>
            </v-card-text>
            <v-card-actions>
              <v-btn @click="increment(todo)" color="primary">さぼり回数</v-btn>
              <span>{{ todo.count }}</span>
              <v-btn @click="decrement(todo)" color="error">間違い(-)</v-btn>
              <v-btn @click="deleteItem(index)">削除</v-btn>
            </v-card-actions>
          </v-card>
        </div>
      </v-container>
    </v-content>
  </v-app>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
      name: "",
      todos: [],
      memo: []
    };
  },
  mounted() {
    this.todos = JSON.parse(localStorage.getItem("todos")) || [];
  },
  methods: {
    templateJson() {
      let setJson = JSON.stringify(this.todos);
      localStorage.setItem("todos", setJson);
    },
    addMemo() {
      this.templateJson();
      this.isActive = false;
    },
    addTodo() {
      if (this.name != "") {
        this.todos.push({
          name: this.name,
          count: 0
        });
      }
      this.templateJson();
      this.name = "";
    },
    increment(todo) {
      todo.count++;
      this.templateJson();
    },
    decrement(todo) {
      if (todo.count > 0) {
        todo.count--;
      }
      this.templateJson();
    },
    deleteItem(index) {
      this.todos.splice(index, 1);
      let setJson = JSON.stringify(this.todos);
      localStorage.removeItem("todos");
      localStorage.setItem("todos", setJson);
    }
  }
};
</script>

vuexに書き変えた際の問題点

悩んだ点として、mountedのthis.$store.state.todos =
JSON.parse(localStorage.getItem("this.$store.state.todos")) ||
の部分をvuexに書き変える部分が分かりませんでした。
一応、データを扱っていたので、gettersで書き変えを試みましたが、授業名を入力すると次のようなエラーを吐きました。
イメージ説明

下記ソースコードです。↓

Count.vue

<template>
  <v-app>
    <v-content>
      <v-container>
        <v-row>
          <v-col cols="6">
            <v-text-field v-model="$store.state.name" label="授業名" @keyup.enter="addTodo" required></v-text-field>
          </v-col>
        </v-row>
        <div v-for="(todo,index) in ($store.state.todos)" :key="todo.name">
          <v-card card_id max-width="344" class="mx-auto">
            <v-card-title>{{todo.name}}</v-card-title>
            <v-card-text>
              <v-text-field label="メモ" v-model="todo.memo" @input="addMemo"></v-text-field>
            </v-card-text>
            <v-card-actions>
              <v-btn @click="increment(todo)" color="primary">さぼり回数</v-btn>
              <span>{{ todo.count }}</span>
              <v-btn @click="decrement(todo)" color="error">間違い(-)</v-btn>
              <v-btn @click="deleteItem(index)">削除</v-btn>
            </v-card-actions>
          </v-card>
        </div>
      </v-container>
    </v-content>
  </v-app>
</template>

<script>
import { mapActions } from "vuex";

export default {
  data() {
    return {};
  },
  mounted() {
    this.$store.state.todos = this.$store.getters.getItemJson;
  },
  methods: {
    ...mapActions([
      "templateJson",
      "increment",
      "decrement",
      "addMemo",
      "addTodo",
      "deleteItem"
    ])
  }
};
</script>

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0,
    name: "",
    todos: [],
    memo: []
  },
  getters: {
    getItemJson(state) {
      state.todo = JSON.parse(localStorage.getItem("state.todos")) || [];
    }
  },
  mutations: {
    templateJson(state) {
      state.todos = JSON.parse(localStorage.getItem("state.todos")) || [];
      let setJson = JSON.stringify(state.todos);
      localStorage.setItem("state.todos", setJson);
    },
    addMemo() {
      this.templateJson();
      this.isActive = false;
    },
    addTodo(state) {
      if (state.name != "") {
        state.todos.push({
          name: state.name,
          count: state.count
        });
      }
      state.name = "";
      this.templateJson();
    },
    increment(state) {
      state.count++;
      this.templateJson();
    },
    decrement(state) {
      if (state.count > 0) {
        state.count--;
      }
      this.templateJson();
    },
    deleteItem(state, index) {
      state.todos.splice(index, 1);
      let setJson = JSON.stringify(state.todos);
      localStorage.removeItem("state.todos");
      localStorage.setItem("state.todos", setJson);
    }
  },
  actions: {
    toggleSideMenu({ commit }) {
      commit("toggleSideMenu")
    },
    templateJson({ commit }) {
      commit("templateJson")
    },
    addMemo({ commit }) {
      commit("addMemo")
    },
    addTodo({ commit }) {
      commit("addTodo")
    },
    deleteItem({ commit }, index) {
      commit("deleteItem", index)
    },
    increment({ commit }, state) {
      commit("increment", state)
    },
    decrement({ commit }, state) {
      commit("decrement", state)
    },
  }
})

 自分のエラーの原因の考察

templateJsonメソッドで、データを保存しているのですがmounted(gettersの getItemJsonメソッド)でデータを取得した実装がうまくいってないので結果的にデータ保存ができていない。自分の見解はこんな感じです。
mountedの部分をvuexでどのように書き変えればvuex書き変え前と変わらない挙動ができますか?
アドバイスあればお願いします。

全コード

➀ vuex書き変え前の上手く挙動する方のブランチのソースコード↓
https://github.com/masal9pse/courageTodo/tree/develop
➁ vuex書き変え後の動かないブランチのソースコード
https://github.com/masal9pse/courageTodo/tree/vuex

参考にしたサイト

➀ https://vuex.vuejs.org/ja/guide/getters.html

➁ https://wp.tech-style.info/archives/742#toc8

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

ストアの値はミューテーションからのみ変更することができます。また、ゲッターはストアのデータを抽出するための機能ですのでゲッターからストアへ値をセットする方法は誤りとなります。
mountedの処理は以下のようにすれば注入可能だと思います。

mutations: {
  setTodos(state) {
    state.todo = JSON.parse(localStorage.getItem("state.todos")) || [];
  }
}
mounted() {
  this.$store.commit('setTodos')
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.19%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る