vuexfire&vuexのstore設計

## TL;DR
vuexfireも従来のvuex storeも必要なのでmodulesを分離させた話。
ずっと```modules/page.js```一枚でやっていたので備忘録もかねて。
&どうせならばとfirestoreで作成

参考: [posva/vuexfire](https://github.com/posva/vuexfire/blob/c8e79bd5dcad3c217f31cb0671119dc6091a02b3/examples/index.html#L102:13)


## 環境

### npm
```
  "vue": "^2.5.13",
  "firebase": "^4.8.1",
  "nuxt": "^1.0.0-rc11",
  "vuexfire": "^3.0.0-alpha.0"
```

vuexfireのfirestore対応はまだalphaなのでご使用は計画的に。
親子関係であるvuefire(開発者がposvaさん同一人物)
[Firestore Roadmap | vuejs/vuefire](https://github.com/vuejs/vuefire/issues/145)
のroadmap見る限り、そろそろな感じ。

### dir構成

```:storeDir
store/
　├ modules/
　│　├ fire.js
　│　└ page.js
　├ actions.js
　├ getters.js
　├ index.js
　└ mutaion-types.js
```

## on code

```js:index.js
import Vue from 'vue'
import Vuex from 'vuex'
import page from './modules/page'
import fire from './modules/fire'
import * as actions from './actions'
import * as getters from './getters'
import createLogger from 'vuex/dist/logger'

Vue.use(Vuex)

const debug = process.env.NODE_ENV !== 'production'
Vue.config.debug = debug

const createStore = () => {
  return new Vuex.Store({
    modules: {
      page, fire
    },
    actions,
    getters,
    strict: false,
    plugins: debug ? [createLogger()] : []
  })
}
export default createStore
```
順番にmodules2つ。

```js:modules/page.js
import * as types from '../mutation-types'

const state = {
  title: ''
}

const mutations = {
  [types.SET_TITLE] (state, title) {
    state.title = title
  }
}

export default {
  state,
  mutations
}
```
mutationsがfirebaseMutationsで埋まる。moduleを分離した理由のひとつ。

```js:modules/fire.js
import { firebaseMutations } from 'vuexfire'

const state = {
  users: [],
  user: {}
}
const mutations = firebaseMutations

export default {
  state,
  mutations
}
```
actionは共用。
vuexfireはmutaionsの記述をしないので、commmitなし。
setUserRef()、意図としてはgetterになるがgetterには非同期処理書けないのでこうゆう形になる。

```js:actions.js

import * as types from './mutation-types'
import firebase from '~/plugins/firebase'
import 'firebase/firestore'
import { firebaseAction } from 'vuexfire'
const db = firebase.firestore()
const usersRef = db.collection('users')

export const setTitle = ({ commit }, title) => {
  commit(types.SET_TITLE, title)
}
export const setUserRef = firebaseAction(({ bindFirebaseRef }, userId) => {
  bindFirebaseRef('fire.users', usersRef, { wait: true })
  bindFirebaseRef('fire.user', usersRef.doc(userId), { wait: true })
})
```

page, fireと返し先のmoduleを```({ xxx })```で指定する。両方渡す方法もあったはず。

```js:getters.js
export const isDebug = ({ page }) => { return process.env.NODE_ENV !== 'production' }
export const pageTitle = ({ page }) => { return page.title }
export const users = ({ fire }) => { return fire.users }
export const user = ({ fire }) => { return fire.user }
```

簡単な表示部分。

```html:XXX.vue
...
<script>
import { mapGetters, mapActions } from 'vuex'

export default {
  computed: {
    ...mapGetters(['user', 'users', 'pageTitle'])
  },
  watch: {
    user: function (val) {
      console.log('change user', val)
    },
    users: function (vals) {
      console.log('change users', vals)
    }
  },
  methods: {
    ...mapActions(['setUserRef', 'setTitle'])
  },
  created () {
    console.log('hello created')
    this.setTitle('this title')
    this.setUserRef('_current_user_')
  }
}
</script>
...
```

となる。

## はまった部分

```js:actions.js
...
export const setUserRef = firebaseAction(({ bindFirebaseRef }, userId) => {
  bindFirebaseRef('fire.users', usersRef, { wait: true })
  bindFirebaseRef('fire.user', usersRef.doc(userId), { wait: true })
})
```
ここの```'fire.user'```部分、```'user'```で試していたのだがうまくいかず。
よく考えれば、moduleがpageなのかfireなのか、指定してないとわからないなと。

## 雑感

- まだモジュール分離の恩恵までたどり着いてないのでなんとも言えない
- かしこくないのでvuexでmapGetters, mapActions以外では基本アクセスしない方向だが、どうなんだろー感。
- 下記みたいな構成もできるし好きにやればいいと思う。どっちかいい理由あるなら教えて欲しい。
- vue.jsたのしい

```js
...
export default new Vuex.Store({
   state,
   mutations: {
     ...VuexFire.mutations,
     ...mutations
   },
   getters,
   actions
})
```