LoginSignup
12

More than 5 years have passed since last update.

vuexfire&vuexのstore設計

Posted at

TL;DR

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

参考: posva/vuexfire

環境

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
のroadmap見る限り、そろそろな感じ。

dir構成

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

on code

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つ。

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を分離した理由のひとつ。

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には非同期処理書けないのでこうゆう形になる。

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 })で指定する。両方渡す方法もあったはず。

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 }

簡単な表示部分。

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>
...

となる。

はまった部分

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たのしい
...
export default new Vuex.Store({
   state,
   mutations: {
     ...VuexFire.mutations,
     ...mutations
   },
   getters,
   actions
})

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
12