VuexのcreateNamespacedHelpersでdispatchの記述を短くしたい
初めてVuexを触ったとき、とくにnamespaceも使わずやってました。
ちなみにmapActions
は使わず、this.$store.dispatch
でしたい派。
this.$store.dispatch
の方がdispatch
してるわー!今dispatchしてるわー感があるので好き。
というのは嘘で、コード見たときに、「アクション叩いてる」っていう部分が、ぱっと見分かりやすかったってのがあります。
問題
namespaced: true
にしてみると、namespace + actionName
と書く必要がでてきます。
methods: { handleClickBefore(e) { this.$store.dispatch('actionName', payload) }, handleClickAfter(e) { this.$store.dispatch('namespace/actionName', payload) } }
こう見てみると、「そんな嫌か?」ってレベルに見えるんです。
typesを分ける
実際開発しだすと、直接文字列で指定することは少なくて、types.js
みたいなのをつくって、中にconst
でミューテーションとかアクション名を書いていきます。
export const namespace = 'File/' export const SET_FILE_LIST = 'SET_FILE_LIST' export const FETCH_FILE_LIST = ' FETCH_FILE_LIST'
こうすると、dispatchの部分は
import * as fileTypes from '@/store/modules/File/types' // ... methods: { handleClick(e) { this.$dispatch(fileTypes.namespace + fileTypes.FETCH_FILE_LIST) } }
このレベルだとまだマシですが、中にはPREFIXがついて長くなるアクション名がでてきます。
this.$dispatch(fooTypes.namespace + fooTypes.PREFIX_PREFIX_ACTION_NAME_FOR_XXX)
ここまでなると、さすがにdispatch
が良いとは言い辛い状況になってきました。
解決
createNamespacedHelpers
というのがVuexに用意されていることを知りました。
Vuex/modules
import { createNamespacedHelpers } from 'vuex' import * as fileTypes from '@/store/modules/file/types' const { mapActions: mapActionsOfFile } = createNamespacedHelpers(fileTypes.namspace) //... methods: { ...mapActionsOfFile([fileTypes.FETCH_FILE_LIST]), handleClick(e) { this[fileTypes.FETCH_FILE_LIST]() } }
結局mapActions
に屈したわけですが、思っていたほど見辛いこともなく、楽に書けるので良いかなといった具合です。
(Vuex噛んでいるところはthis[types.XXXX]
ってなるので、他とか区別できているので)
その他も
mapState
やmapGetteres
でmapState(namespace, [xxxx])
としていたのも同じく解決です。
また、複数のモジュールを使うときも明確になりますね。
import * as fileTypes from '@/store/modules/File/types' import * as userTypes from '@/store/modules/User/types' const { mapState: mapStateOfFile, mapGetters: mapGettersOfFile } = createNamespacedHelpers(fileTypes.namesace) const { mapState: mapStateOfUser, mapGetters: mapGettersOfUser } = createNamespacedHelpers(userTypes.namesace) //... computed: { ...mapStateOfFile(['fileList']), ...mapStateOfUser(['userList']), ...mapGettersOfFile(['imageList', 'pdfList']) }
みたいな具合で。
一つのモジュールしか使わないなら、import * as types from '@/store/modules/xxxx'
でいいんですけどね。