typeof Diary

VimとかJSとか。やったことのメモ。自分のため。

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]ってなるので、他とか区別できているので)

その他も

mapStatemapGetteresmapState(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'でいいんですけどね。

参考記事