今回達成すること
nuxt-typed-vuex
のインストールとセットアップを行います。
そしてVuexストアの値をVueファイルから呼び出し、挙動や使い方を学びます。
最初にブランチを切っておきましょう。
% git checkout -b 20220109_setup_nuxt_typed_vuex
% git branch
* 20220109_setup_nuxt_typed_vuex
nuxt-typed-vuexをインストールする
nuxt-typed-vuex
をインストールします。
% yarn add nuxt-typed-vuex
Vuexをラップしたモジュールなのでdependenciesにインストールします。
今回はv0.2.0を使用します。
% yarn list --pattern nuxt-typed-vuex
└─ nuxt-typed-vuex@0.2.0
buildModules
に登録します。
nuxt.config.js
export default {
buildModules: [
// https://typed-vuex.roe.dev
'nuxt-typed-vuex'
],
}
Vuexファイルを作成する
Vuexを扱うファイルを作成します。
storeディレクトリ直下に
% touch store/index.ts
nuxt-typed-vuexを使ったVuexの基本構文
作成した
store/index.ts
// typed-vuex setup: https://typed-vuex.roe.dev/getting-started/getting-started-nuxt
import { getAccessorType, getterTree, mutationTree, actionTree } from 'typed-vuex'
export const state = () => ({
/* state */
})
export const getters = getterTree(state, {
/* getter */
})
export const mutations = mutationTree(state, {
/* mutation */
})
export const actions = actionTree({ state, getters, mutations }, {
/* action */
})
getterTree
、mutationTree
、actionTree
がnuxt-typed-vuex
の構文となります。
この中に関数を記述することで、自動でVuexストアの型定義を返してくれます。
Vuexストアの型をエクスポートする
型定義をgetAccessorType
でコンパイルし、型宣言ファイルへエクスポートします。
store/index.ts
export const actions = actionTree({ state, getters, mutations }, {
/* action */
})
// 一番下に追加
export const accessorType = getAccessorType({
state,
getters,
mutations,
actions,
modules: {
/* sub modules */
}
})
modules: {}とは
modules: {}
には、
例えばmodules: {}
内は以下のように書きます。
store/index.ts(例)
import * as post from '~/store/post'
export const accessorType = getAccessorType({
modules: {
post
}
})
module.d.tsファイルを作成する
型宣言ファイルを作成します。
モジュールの型宣言ファイルとして、プロジェクトディレクトリ直下に
nuxt-typed-vuex
以外にも、アプリ全体で使用するグローバルなモジュールの型定義ファイルとします。
これは独自ルールなので、ディレクトリパスやファイル名は管理しやすいように変更してOKです。
% mkdir types && touch $_/module.d.ts
interface Vue
と、interface NuxtAppOptions
にVuexストアの型を追加します。
types/module.d.ts
import { accessorType } from '~/store'
/*
nuxt-typed-vuexの型定義をVueとNuxtに登録
Doc: https://typed-vuex.roe.dev/getting-started/getting-started-nuxt#creating-type-definitions
*/
declare module 'vue/types/vue' {
interface Vue {
$accessor: typeof accessorType
}
}
declare module '@nuxt/types' {
interface NuxtAppOptions {
$accessor: typeof accessorType
}
}
-
declare
... 宣誓の意味を持つ。この型のモジュールをエクスポートすることを誓います。ということ。
これでnuxt-typed-vuex
が使用できるようになりました。
Vuexストアは$storeではなく$accessorを使用する
nuxt-typed-vuex
を使用したVuexは、$accessor
で呼び出します。
$store
で呼び出しするとTypeエラーになるので注意してください。
コンテキスト $accessorの格納場所
Nuxtコンテキストには、app
プロパティ以下に$accessor
が格納されています。
Vueファイル
@Component
export default class IndexPage extends Vue {
asyncData ({ app: { $accessor } }) {
const hoge = $accessor.hoge
}
}
nuxt-typed-vuexの型定義
それではnuxt-typed-vuex
がどのような挙動をするか学びましょう。
stateの型付け
state
内のデータの型付けにはas
を使用します。
state
全体の型を使用する場合は、ReturnType<typeof state>
で型定義を行います。
store/index.ts
export const state = () => ({
count: 0 as number
})
type RootState = ReturnType<typeof state>
gettersの型付け
getters
は、return
の値によって自動で型定義を行います。
下記コードは number |'カウントゼロ'
の型が定義されます。
store/index.ts
export const getters = getterTree(state, {
countValue: (state: RootState, _getters) => (
state.count || 'カウントゼロ'
)
})
mutationsの型付け
mutations
の戻り値はvoid
型が定義されます。
引数に渡すpayload
は自分で型を定義します。
store/index.ts
export const mutations = mutationTree(state, {
setCount (state: RootState, payload: number) {
state.count += payload
}
})
エディタで解析された型定義
actionsの型付け
actions
の戻り値はvoid
型が定義されます。
この型は自ら定義することも可能です。
メソッドの引数(value: number
)には自ら型を定義を行います。
store/index.ts
export const actions = actionTree({ state, getters, mutations }, {
countUp ({ commit }, value: number) {
commit('setCount', value)
}
})
{ commit }
などのコンテキストの型は、nuxt-typed-vuex
がActionContext
として自動で型定義してくれます。
下画像を見て分かる通り、ActionContext
には state
、getters
、mutations
の型が定義されています。
これはactionTree()
に渡したstate
、getters
、mutations
を解析し型定義を行なっています。
エディタで解析された型定義
例えばgetters.countValue
をArray型に代入しようとするとエラーとなります。
これはアクションメソッドのコンテキストの型が正しく定義されている証拠です。
export const actions = actionTree({ state, getters, mutations }, {
countUp ({ commit, getters }, value: number) {
/*
Type Error
Type 'number | "カウントゼロ"' is not assignable to type '[]'.
Type 'number' is not assignable to type '[]'.
*/
const count: [] = getters.countValue
}
})
VueファイルからのVuexを呼び出そう
Vuexストアで宣言した値と関数を
pages/index.vue
<template>
<div>
<v-container>
<!-- v-container直下に追加 -->
<v-card>
<v-card-title>
nuxt-typed-vuexのテスト
</v-card-title>
<v-card-text>
state.count: {{ $accessor.count }}<br>
getters:countValue: {{ $accessor.countValue }}
</v-card-text>
<v-card-actions>
<v-btn
@click="$accessor.countUp(1)"
>
count up
</v-btn>
</v-card-actions>
</v-card>
<!-- ここまで -->
</template>
ブラウザにVuexストアの値が表示されました。
COUNT UPボタンでStateの値が増えていることも確認してください。
stateやactionメソッドは$accessor直下に紐づく
従来のVuexと大きく変わる点は、state
、getters
、mutations
、acrions
で宣言したデータや関数は、全て$accessor
直下のプロパティに追加されます。
console.log(this.$accessor)
$accessor: {
count: (...)
countValue: (...)
setCount: ƒ (mutationPayload)
countUp: ƒ (actionPayload)
}
サブモジュールは$accessor.<プロパティ名>で呼び出す
store/index.ts(例)
import * as post from '~/store/post'
export const accessorType = getAccessorType({
modules: {
// 呼び出しプロパティ名
post
}
})
この時modules
で指定したプロパティ名で呼び出します。
pages/inde.vue(例)
<div>
{{ $accessor.post.<State or function> }}
</div>
それではコミットして作業を終わります。
% git add -A
% git commit -m "Add module nuxt-typed-vuex and initial settings"
次回は?
今回はnuxt-typed-vuex
のインストールとセットアップ、挙動とVuexの扱い方を学びました。
次回は、VuexにContentfulのAPIデータの型定義やStateの用意を行います。