はじめに
Vuex で dispatch するとき、action 名とかどうやって取ってくるのがベストなのかなと
補完を効かせてタイポ無くメソッド呼びたい!
ということで最近は Vuex 使うときはもっぱら vuex-module-decorators ばかり使っています。
導入
↓ 通りに ~/store/index.ts を作成して ~/utils/store-accessor.ts に書いてある store モジュールを展開する感じ
https://github.com/championswimmer/vuex-module-decorators#accessing-modules-with-nuxtjs
~/store/index.ts:
import { Store } from 'vuex';
import { initialiseStores } from '~/utils/store-accessor';
const initializer = (store: Store<any>) => initialiseStores(store);
export const plugins = [initializer];
export * from '~/utils/store-accessor';
~/utils/store-accessor.ts:
/* eslint-disable import/no-mutable-exports */
import { Store } from 'vuex';
import { getModule } from 'vuex-module-decorators';
import News from '@/store/news';
let newsStore: News;
function initialiseStores(store: Store<any>): void {
newsStore = getModule(News, store);
}
export { initialiseStores, newsStore };
サンプルで NEWS を取得する Store を書いていきます
~/store/news.ts
import { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators';
// 何かしらのapiメソッド
import api from '@/api';
interface News {
id: string;
title: string;
body: string;
}
@Module({ name: 'news', namespaced: true, stateFactory: true })
export default class News extends VuexModule {
public list: News[] = [];
public one: News | null = null;
@Mutation
public setList(list: News[]) {
this.list = list;
}
@Mutation
public setOne(value: News) {
this.one = value;
}
@Action({ rawError: true })
public async fetchList() {
// News取得のAPI
await api
.newsList()
.then((res) => {
this.setList(res.data);
})
.catch((err) => {
throw Error(err);
});
}
@Action({ rawError: true })
public async fetchOne(id: string) {
// News取得のAPI
await api
.newsGet(id)
.then((res) => {
this.setOne(res.data);
})
.catch((err) => {
throw Error(err);
});
}
}
呼び出し側は ↓ のように書きます
~/pages/index.vue
<template>
<div>
<ul>
<li v-for="item in list" :key="item.id">
<nuxt-link :to="`/news/${item.id}`">
{{ item.title }}
</nuxt-link>
</li>
</ul>
</div>
</template>
<script>
import Vue from 'vue;
import { newsStore } from '@/store';
export default Vue.extend({
// middleware か asyncDataで取得
async middleware({ error }) {
await newsStore.fetchList()
.catch(err => error(err));
},
computed: {
list() {
return newsStore.list;
}
}
});
</script>
おわり
1 つ、2 つの Store だと恩恵があまり感じられませんが、
数が増えてくるといちいちメソッド名、state 名は覚えてられないです。
なので補完でタイポ無し、それっぽそうな名前が選べるのでめちゃ便利です