【Vuex】Vuex をざっくり理解 

`Vuex`について勉強してみて、ざっくりと理解できた内容についてまとめてみました。
間違いなどあればご指摘いただけると幸いです。

# この記事でわかること
・`Vuex` ってざっくりどんな仕組みになっているのか。
・使うことで何が嬉しいのか。

# Vuex とは
ものすごくざっくり言うと、**Vuexはアプリのデータを管理するための簡易的なDBみたいなものです。**
極端に言うと単なる入れ物みたいなイメージだと私は考えています。

なので、やってることは
**入れ物を用意して、そこに値を出し入れしているだけ**

# Vuexのメリット
**データを1箇所で集中管理でき、ソースコードの可読性が向上、+デバックが容易になる。**

`Vuex`のメリットを語るには、`Vuex`がない世界を想像すると理解しやすいです。

`vue`では、コンポーネント間で`props`で親から子へデータを受け渡し、
`$emit`で子から親にデータ送ることができます。

開発が進むことで、大体コンポーネントの種類も増えていきます。

コンポーネントが増えることで、当然ながらデータの受け渡しも増大します。

その結果、**データがどこで変更されたか等のデータの流れが追いづらくなり、
メンテナンスが困難なコードとなってしまい困ります。( ；∀；)**

このような問題を解決するために生まれたのが`Vuex`です。

# Vuex 全体の流れ

`Vuex`の中心にいるのが、**store**と言われるアプリケーションのデータ状態を保持するコンテナで、
この`store`には４つの機能があります。（`state, mutations, actions, getters`）
それぞれの役割についてみていきましょう。

※使用しているソースコードは[公式](https://vuex.vuejs.org/ja/)から引用しています。

## state
**stateは、アプリケーション全体のデータの状態を管理します。**
ここで管理したいデータを「名前： 初期値」みたいな形で定義します。

```javascript
const store = createStore({
  // 「名前： 初期値」 の形で定義する
  state: {
    count: 1
  }
})
```


※ アプリケーションごとに1つしかストアは持たないことに注意が必要です。
## mutations
**mutationsは、stateの更新だけを行います。**

**muitationsには非同期処理を含んではいけないことに注意が必要です。**
その理由は、非同期処理とstateの管理が混在すると、状態管理が追跡しにくくなるからです。

`Vuex` のストアの状態を変更できる唯一の方法は、`mutations`をコミット（実行）することです。

使い方は以下のように、`Vuex`の状態（state）を第1引数として受け取り、状態の変更を行います。
```javascript
const store = createStore({
  state: {
    count: 1
  },
  mutations: {
    // ステート管理に必要なメソッドを用意する
    increment (state) {
      // 状態を変更する
      state.count++
    }
  }
})
```

また、引数の指定も可能で、この追加の引数は、特定のミューテーションに対するペイロードと呼ばれます。
```javascript
// ...
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
```

## actions
**actionsは、mutationsの呼び出しを行います。**
**また、actions自体は直接stateを変更できないことに注意が必要です。**
また、非同期なAPI通信もここで行います。

```javascript
const store = createStore({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      // mutationsを呼び出している
      context.commit('increment')
    }
  }
})
```
ここで登場した`context`はコンテキストオブジェクトと呼ばれ、ストア配下にアクセスするために
以下のプロパティを提供します。
[[Vuex] mutations, actions, gettersの引数について](https://qiita.com/after666/items/7e94d61fed89406ae59a) を参考にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2508607/a3553b4f-9d08-8a97-3479-657558fdbefc.png)



今回で言うと、`contextオブジェクト`にある`commit`を呼びだし、`mutations`を実行しています。


また、渡された`contextオブジェクト`からプロパティである`commit`を取り出し、
同名の変数に渡すことで以下のように短縮して記述することもできます。

```javascript
///
  actions: {
    increment ( { commit } ) {
      commit('increment')
    }
  }
})
```

## getters
**gettersは、stateの値を算出したものを返す場合に役立ちます。**

`computed`と使い方はかなり近いです。

`state`の内容を演算/加工処理をコンポーネント側で書くことできますが、
データの集中管理という観点で`store`の中に書いた方が利便性が向上します。

以下が具体的なコードです。
``` javascript
const store = createStore({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos (state) {
      return state.todos.filter(todo => todo.done == true)
    }
  }
})
```
`getters`は第1引数として、`state`を受け取ります。
`filter`は`javascript`標準のメソッドで条件式`(todo.done == true)`を満たす要素を取得します。



## まとめ
上記をまとめると以下のような図式になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2508607/28da3dc9-ed5e-e3fc-11f4-1fb7f74a1794.png)


上の図のように、データの流れが一方通行になっています。
非同期通信を`actions`で行い、その後に`mutations`を実行することで`state`を変更している。
`state`が変更されたことを検知し、`getters`で`state`のデータを再取得して、画面に反映させる仕組みです。

# 最後に
説明していてなんですが、`Vuex`で管理されるデータはどこからでも参照、変更できる
グローバル変数であるため、使いどころも難しいと感じます。

影響範囲が大きい分、意識しないといけないものが増えるので、読むときや修正する際に
精神的な負担が高いコードになってしまう危険性もあるみたいです。

ここら辺はトレードオフで考えなければいけないんだなぁと。

# 参考文献
[これからはじめるVue.js 3実践入門](https://www.amazon.co.jp/%E3%81%93%E3%82%8C%E3%81%8B%E3%82%89%E3%81%AF%E3%81%98%E3%82%81%E3%82%8BVue-js-3%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80-%E5%B1%B1%E7%94%B0-%E7%A5%A5%E5%AF%9B/dp/4815613362/ref=pd_lpo_1?pd_rd_i=4815613362&psc=1)