初心者がVuexの公式ガイドを勉強するメモ コアコンセプト　ステート編

# Vuex コアコンセプト ステート編
## 今回のお題は、こちらです。
### https://vuex.vuejs.org/ja/core-concepts.html

### 構成

```
.
├── README.md
├── index.html
├── package-lock.jsona
├── package.json
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── main.js
│   └── store.js
└── webpack.config.js
```

## ステート
### Vuex の状態を Vue コンポーネントに入れる

* App.vue

```html

<template lang="pug">
  #app
    Counter
</template>

<script>
import Vue from 'vue'
import store from './store.js'

const Counter = {
  name: 'Counter',
  template: `<div>{{ count }}</div>`,
  computed: {
    //- アロー関数
    count: () => store.state.count
  }
}
Vue.component('Counter', Counter)

export default {
  name: 'app',
  data () {
    return {
      privateState: {},
    }
  },
  computed: {
    count () {
      return store.state.count
    }
  },
  methods: {
    increment() {
      return store.commit('increment')
    },
    decrement() {
      return store.commit('decrement')
    }
  }
}
</script>
```

* src/store.js

``` js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 51
  },
  mutations: {
    increment: (state) => {
      state.count++
    },
    decrement: state => state.count--,
  }
})
export default store
```

* es6 の省略記法は、見比べていたら慣れてくるので、使うようにします。
* storeのstateをコンポーネントのcomputedを使って、表示させているだけです。

### ルートインスタンスに store オプションを渡す

* App.vue

``` html

<template lang="pug">
  #app
    Counter
    button(@click="increment") +
    button(@click="decrement") -
</template>

<script>
import Vue from 'vue'
import store from './store.js'

const Counter = {
  name: 'Counter',
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}
Vue.component('Counter', Counter)

export default {
  name: 'app',

  //
  // store option
  //

  store,
  data () {
    return {
      privateState: {},
    }
  },
  computed: {
    count () {
      return this.$store.state.count
    }
  },
  methods: {
    increment() {
      return this.$store.commit('increment')
    },
    decrement() {
      return this.$store.commit('decrement')
    }
  }
}
</script>
```

* ルートで storeを指定することで、別ファイルのコンポーネントであろうが、すべて this.$store で storeにアクセスできるみたいです。
* thisを使っている箇所は、参照先が異なるので、アロー関数から変更しています。

### コンポーネントを別ファイルにしてみる。
* 別ファイルにして、storeをimport にしなくても問題ないことを確認します。
* 構成

```
.
├── README.md
├── index.html
├── package-lock.json
├── package.json
├── src
│   ├── App.vue
│ * ├── Counter.vue
│   ├── assets
│   │   └── logo.png
│   ├── main.js
│   └── store.js
└── webpack.config.js
```

* src/Counter.vue

```html

<template lang="pug">
  div {{ count }}
</template>

<script>
export default {
  name: 'Counter',
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

</script>

<style lang="scss" scoped>
</style>

```

* App.vue

```html

<template lang="pug">
  #app
    Counter
    button(@click="increment") +
    button(@click="decrement") -
</template>

<script>
import Vue from 'vue'
import store from './store.js'
import Counter from './Counter'

Vue.component('Counter', Counter)

export default {
  name: 'app',
  store,
  data () {
    return {
      privateState: {},
    }
  },
  computed: {
    // count () {
    //   return this.$store.state.count
    // }
  },
  methods: {
    increment() {
      return this.$store.commit('increment')
    },
    decrement() {
      return this.$store.commit('decrement')
    }
  }
}
</script>
```
* 表示部分を別ファイルにしましたが、特に問題なく表示されていますね。



### mapState ヘルパー

* Counter.vue

``` html

<template lang="pug">
  div
    div {{ count1 }}
    div {{ count2 }}
    div {{ count3 }}
</template>

<script>
import { mapState } from 'vuex'

export default {
  name: 'Counter',
  data: () => ({
    localCount: 999
  }),
  computed: mapState({
    count1: state => state.count,
    count2: 'count',
    count3 (state) {
      return state.count + this.localCount
    }
  })
}

</script>

<style lang="scss" scoped>
</style>

```

* App.vue

``` html
<template lang="pug">
  #app
    Counter
    button(@click="increment") +
    button(@click="decrement") -
</template>

<script>
import Vue from 'vue'
import store from './store.js'
import Counter from './Counter'

Vue.component('Counter', Counter)

export default {
  name: 'app',
  store,
  data () {
    return {
      privateState: {},
    }
  },
  computed: {
  },
  methods: {
    increment() {
      return this.$store.commit('increment')
    },
    decrement() {
      return this.$store.commit('decrement')
    }
  }
}
</script>

```

* mapStateヘルパーを使うことで、computedでの関数を纒めて、作れるみたいですね。
* count1 は、アロー省略記法です。
* count2 は vuexの省略記法みたいです。
* count3 は、thisの関係で通常の関数です。
* this.$storeで書くより楽ですね。

#### 配列で渡す
* Counter.vue


```html

<template lang="pug">
  div
    div {{ count }}
</template>

<script>
import { mapState } from 'vuex'

export default {
  name: 'Counter',
  data: () => ({
    localCount: 999
  }),
  computed: mapState([
    'count'
  ])
  // computed: mapState({
  //   count1: state => state.count,
  //   count2: 'count',
  //   count3 (state) {
  //     return state.count + this.localCount
  //   }
  // })
}

</script>

<style lang="scss" scoped>
</style>
```
* 名前を変えないのであれば配列で渡すとさらに、省略できますね。



### オブジェクトスプレッド演算子

* App.vue

``` html

<template lang="pug">
  div
    div {{ count }}
    div {{ localCount }}
    div {{ localComputed }}
</template>

<script>
import { mapState } from 'vuex'

export default {
  name: 'Counter',
  data: () => ({
    localCount: 999
  }),
  computed: {
    localComputed () {
      return this.localCount + 1
    },
    ...mapState([
      'count'
    ])
  }
}

</script>

<style lang="scss" scoped>
</style>


```
* スプレッド演算子は、スマートにローカル側とstore側を連結できます。

* ステート編は、これで終了です。