Vuexを触ってみる

開発版ビルドでとりあえず中身を覗いてみます。[参照元](https://vuex.vuejs.org/ja/)

```
$ git clone https://github.com/vuejs/vuex.git node_modules/vuex

$ npm install

$ npm run build
```
エディタを再起動して、

```
$ cd VUEX/

$ npm run dev
```

[ブラウザで、確認！](http://localhost:8080/)
![スクリーンショット 2021-08-31 16.28.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/8c324466-a7ea-f400-2a27-fcdd6b6e1b7e.png)
##・Counter 内実装
```app.js
import Vue from 'vue'
import Counter from './Counter.vue'
import store from './store'

new Vue({
  el: '#app',
  store,
  render: h => h(Counter)
}) 
```

```Counter.vue
<template>
  <div id="app">
    Clicked: {{ $store.state.count }} times, count is {{ evenOrOdd }}.
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementIfOdd">Increment if odd</button>
    <button @click="incrementAsync">Increment async</button>
  </div>
</template>

<script>
import { mapGetters, mapActions } from 'vuex'

export default {
  computed: mapGetters([
    'evenOrOdd'
  ]),
  methods: mapActions([
    'increment',
    'decrement',
    'incrementIfOdd',
    'incrementAsync'
  ])
}
</script>
```

```index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>vuex counter example</title>
    <link rel="stylesheet" href="/global.css">
  </head>
  <body>
    <div id="app"></div>
    <script src="/__build__/shared.js"></script>
    <script src="/__build__/counter.js"></script>
  </body>
</html>
```
そのまま翻訳かけたので、見苦しかったらすみません。

```store.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// ルートのステートオブジェクトです。
// 各Vuexインスタンスは、1つのステートツリーに過ぎません。
const state = {
  count: 0
}

// ミューテーションは、実際にステートを変異させる操作です。
// 各ミューテーションハンドラは、最初の引数としてステートツリー全体を取得します。
// 最初の引数としてステートツリー全体を取得し、その後に追加のペイロード引数が続きます。
// ミューテーションは同期していなければならず、プラグインはデバッグのために
// デバッグ目的でプラグインに記録されることがあります。
const mutations = {
  increment (state) {
    state.count++
  },
  decrement (state) {
    state.count--
  }
}

// アクションは、副作用を引き起こす関数で、次のようなものがあります。
// 非同期の操作を行うことができます。
const actions = {
  increment: ({ commit }) => commit('increment'),
  decrement: ({ commit }) => commit('decrement'),
  incrementIfOdd ({ commit, state }) {
    if ((state.count + 1) % 2 === 0) {
      commit('increment')
    }
  },
  incrementAsync ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('increment')
        resolve()
      }, 1000)
    })
  }
}

// ゲッターは関数です。
const getters = {
  evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd'
}

// Vuexのインスタンスは、state、mutations、action.phpを組み合わせて作成されます。
// とゲッターを組み合わせて作成します。
export default new Vuex.Store({
  state,
  getters,
  actions,
  mutations
})
```
![スクリーンショット 2021-08-31 17.04.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/bcdce644-fd55-700d-5839-4182fa88d73b.png)


`+`を押すと、クリックカウントが増えて`-`を押すと減ります。`Increment if odd`ボタンを押すと奇数の時にカウントが増えて`Increment async`エイシンクボタンで押した回数だけ一秒後にカウントが増える同期処理がされます。

##・Counter with Hot Reload 内実装

```store/actions.js
export const increment = ({ commit }) => {
  commit('increment')
}
export const decrement = ({ commit }) => {
  commit('decrement')
}

export const incrementIfOdd = ({ commit, state }) => {
  if ((state.count + 1) % 2 === 0) {
    commit('increment')
  }
}

export const incrementAsync = ({ commit }) => {
  setTimeout(() => {
    commit('increment')
  }, 1000)
}
```

```store/getters.js
export const count = state => state.count

export const recentHistory = state => {
  return state.history
    .slice(-5)
    .join(', ')
}
```

```store/index.js
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import * as getters from './getters'
import * as actions from './actions'
import * as mutations from './mutations'

Vue.use(Vuex)

const state = {
  count: 0,
  history: []
}

const store = new Vuex.Store({
  state,
  getters,
  actions,
  mutations
})

if (module.hot) {
  module.hot.accept([
    './getters',
    './actions',
    './mutations'
  ], () => {
    store.hotUpdate({
      getters: require('./getters'),
      actions: require('./actions'),
      mutations: require('./mutations')
    })
  })
}

export default store
```

```store/mutations.js
export const increment = state => {
  state.count++
  state.history.push('increment')
}

export const decrement = state => {
  state.count--
  state.history.push('decrement')
}
```

```app.js
import Vue from 'vue'
import store from './store'
import CounterControls from './CounterControls.vue'

new Vue({
  el: '#app',
  store,
  render: h => h(CounterControls)
})
```

```CounterControls.vue
<template>
  <div>
    Value: {{ count }}
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementIfOdd">Increment if odd</button>
    <button @click="incrementAsync">Increment async</button>
    <div>
      <div>Recent History (last 5 entries): {{ recentHistory }}</div>
    </div>
  </div>
</template>

<script>
import { mapGetters, mapActions } from 'vuex'

export default {
  computed: mapGetters([
    'count',
    'recentHistory'
  ]),
  methods: mapActions([
    'increment',
    'decrement',
    'incrementIfOdd',
    'incrementAsync'
  ])
}
</script>
```

```index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>vuex counter example</title>
    <link rel="stylesheet" href="/global.css">
  </head>
  <body>
    <div id="app"></div>
    <script src="/__build__/shared.js"></script>
    <script src="/__build__/counter-hot.js"></script>
  </body>
</html>
```

![スクリーンショット 2021-08-31 17.29.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/28b61e8c-b8ed-2c23-82f7-192716db2e1c.png)

`Value`にカウントされると同時に、`Recent History`に行われた処理が表示されます。`button`に`@click`メソッドに引数を渡してイベントを発火させています。`@click`イベントは関数を呼ぶことができ、上では`methods`で定義したものが呼ばれています。

次回、`Shopping Cart Example`を見てみます。