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
})