1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Vuexを理解する

Posted at

はじめに

最近仕事でVuexを理解する必要が出てきたので、自分の理解のためにメモしておきます。

Vuexとは

VuexはVue.jsにおいて、データの受け渡しを便利してくれるライブラリ。
通常のVue.jsでは、データを他のコンポーネントに渡す際にprops$emitを使います。コンポーネント数が少ない場合はこれでも大丈夫なのですが、コンポーネント数が増えたり、階層が深くなると、素のVue.jsではデータの管理が難しくなってしまいます。

そんなデータ管理の難しさを解消してくれるのがVuexです。今回は以下の点について説明してあります。

  • state
  • getters
  • mutations
  • actions

Vuexを触ってみる

stateを使ってみる

以下でプロジェクト作成、Vuexインストール後にlocalhost:8080にアクセスしてサンプル画面がでていることを確認します。

% vue create vuex-demo
% cd vuex-demo
% npm install vuex
% npm run serve

まずは、Vuexを使うための設定をmain.jsに記述します。

vuex-demo/src/main.js
import { createApp } from "vue";
import App from "./App.vue";
import store from '../store' // vuexを使う設定

const app = createApp(App)

app.use(store) //vuexを使う設定
app.mount('#app')

storeを使うための記述をvuex-demo/store/index.jsに追記します。

vuex-demo/store/index.js
import { createStore } from "vuex";

export default createStore({
    state: {
        message: 'Hello Vuex!'
    }
});

最後にvueファイルにstoreで定義したメッセージを呼び出してみます。
呼び出し方はthis.$store.state.~です。

vuex-demo/src/App.vue
<template>
  <div id="app">
    <h1>{{ this.$store.state.message }}</h1>
  </div>
</template>

<script>
export default {
  name: 'app',
}
</script>

store.stateにメッセージを記述することで、他のコンポーネントでもmessageを参照したいときはApp.vueと同じように書けばよいのです。それを確認します。

App.vueではなくcomponents配下にファイルを作成し、this.$store.state.messageを追記し、画面に同じメッセージが表示されることを確認します。

vuex-demo/src/components/contens.vue
<template>
    <h2>{{ this.$store.state.message }}</h2>
</template>

<script>
export default ({
    name: 'sampleContents',
})
</script>

App.vueも追記をしていきます。

vuex-demo/src/App.vue
<template>
  <div id="app">
    <h1>{{ this.$store.state.message }}</h1>
    <sampleContents></sampleContents>
  </div>
</template>

<script>
import sampleContents from './components/contents.vue'

export default {
  name: 'app',
  components: {
    sampleContents
  }
}
</script>

画面は以下のようになるはずです。stateファイルで同じ内容のmessageを参照できることがわかると思います。
スクリーンショット 2022-07-24 16.14.42.png

gettersを使ってみる

storeの状態を算出するために使うのがgettersです。下のように書くことで条件による絞り込みを行うことができます。computed的なことを実行することができるものです。

vuex-demo/store/index.js
import { createStore } from "vuex";

export default createStore({
    state: {
        message: 'Hello Vuex!',
        // gettersのためにデータを追加
        todos: [
            {id: 1, text: 'Learn Vuex', done: true},
            {id: 2, text: 'Learn Vue.js', done: false},
            {id: 3, text: 'Learn Python', done: true},
            {id: 4, text: 'Learn Node.js', done: false},
            {id: 5, text: 'Learn Julia', done: true}
        ]
    },
    // gettersを追加!
    getters: {
        // 何の変哲ものない書き方?
        doneTodos (state) {
            return state.todos.filter(todo => todo.done)
        },
        // プロパティスタイルアクセスの書き方
        doneTodosCount (state, getters) {
            return getters.doneTodos.length
        },
        // メソッドスタイルアクセスの書き方
        getTodoById: (state) => (id) => {
            return state.todos.find(todo => todo.id === id);
        }
    }
});

呼び出し方は

vuex-demo/src/components/contents.vue
<template>
    <h2>{{ this.$store.state.message }}</h2>
    <h3>all todo </h3>
    <li v-for="todo in $store.state.todos" v-bind:key="todo.id">
        {{ todo }}
    </li>
    <h3>done todos is</h3>
    <li v-for="doneTodo in doneTodos" v-bind:key="doneTodo.id">
        {{ doneTodo }}
    </li>
    <p>count is {{ doneTodosCount }}</p>
    <p>id=2 todo is {{ getTodoById }}</p>
</template>

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

export default ({
    name: 'sampleContents',
    computed: {
        // mapGettersを使って読み込むことや
        ...mapGetters({
            doneTodos: 'doneTodos',
            doneTodosCount: 'doneTodosCount',
        }),
        // 下記のような方法で読み込むことも可能
        getTodoById () {
            return this.$store.getters.getTodoById(2);
        }
    },
})
</script>

スクリーンショット 2022-07-24 17.21.31.png

mutationを使ってみる

index.jsがどんどん大きくなってくるので、該当部分だけ抜き出します。
mutationはstateの状態を変えることができます。例えば、新しくToDoリストを追加することができます。

vuex-demo/store/index.js
...
    mutations: {
        addTodo (state, todo) {
            state.todos.push( todo );
        }
    }
...

mutationが実行されるためにはcommitがトリガーになります。
つまり、commitがないことにはstateの状態を変えることができません。

vuex-demo/src/components/contents.vue
<template>
    ...
    <form @submit.prevent="addTodo">
        <input
            type="text"
            v-model="text"
        />
        <button>Add ToDo</button>
    </form>
    ...
</template>

<script>
    ...
    methods: {
        addTodo () {
            // commitを使うことでstoreのtodoの状態を変えることができる
            this.$store.commit('addTodo', {
                "id": this.$store.state.todos.length + 1,
                "text": this.text,
                "done": false
            });
            this.text = '';
        },
    ...
</script>

スクリーンショット 2022-07-24 18.38.36.png

actionを使ってみる

actionはmutationと似ていますが、以下のような特徴があります。

  • 状態の変更するのではなく、mutationのcommitを行なっている
  • mutationと違い、非同期処理を含むことができる

mutationと違って、条件によって特定の処理を入れることができます。今回はidを設定できるようにします。

vuex-demo/store/index.js
    ...
    actions: {
        addTodoSpecifingId ({commit}, number) {
            commit('addTodo', {id: number, text: 'Learn Linux', done: false});
        }
    }
vuex-demo/src/components/contents.vue
<template>
   ...
    <h2>Add Todo by Actions</h2>
    <form @submit.prevent="addDoneTodo">
        <input
            type="integer"
            v-model="specific_id"
        />
        <button>Add ToDo by actions</button>
    </form>
    ...
</template>

<script>
    ...
    methods: {
        ...
        addDoneTodo () {
            // actionはdispatchによって呼び出される
            this.$store.dispatch('addTodoSpecifingId', this.specific_id)
        },
    ...
</script>

最後に

書きながらまとめることでなんとなくVuexを理解できた気がする。
公式が言っていた「状態管理パターン」の意味はstate, getter, mutation, actionがわかれば完璧ですね。

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?