TypeScript
Vuex
nuxt.js

【Nuxt.js】Todoリストで理解するTypeScriptでVuex入門

簡単にTypeScriptでVuex入門をしたかったのでTodoリストを作ってみました。

(※pageの記載はtsですが、ストアはjsで実装しています)


この記事で伝えること


  • pages/index.vueでのストアの呼び出し方

  • JavaScriptとTypeScriptの比較


この記事で伝えないこと


  • 環境構築

  • TypeScriptでのストアの書き方

  • Vuexの解説


①ストアを作成(JavaScript)

下記リンクを参考にストアを作っていきます

* Vuex ストア - Nuxt.js

ディレクトリ構成


  • pages


    • index.vue(TypeScriptでのtodoリスト)

    • todos.vue(JavaScriptでのtodoリスト)



  • store(ストアはJS・TS共に共通)


    • index.js

    • todos.js




store/index.js

export const mutations = {

add(state, text) {
state.todos.list.push({
text: text,
done: false
})
},
remove(state, { todo }) {
state.list.splice(state.list.indexOf(todo), 1)
},
toggle(state, todo) {
todo.done = !todo.done
}
}


store/todos.js

export const state = () => ({

list: []
})

モジュールモードなので、明示的に new Vuex.Store する必要はありません。


モジュールモード: store ディレクトリ内のすべての *.js ファイルが 名前空間付きモジュール に変換されます(index はルートモジュールとして存在します)



②まずはお馴染みのJavaScriptで実装


pages/todos.vue

<template>

<ul>
<li v-for="(todo, i) in todos" :key="i">
<input type="checkbox" :checked="todo.done" @change="toggle(todo)" />
<span :class="{ done: todo.done }">{{ todo.text }}</span>
</li>
<li>
<input placeholder="What needs to be done?" @keyup.enter="addTodo" />
</li>
</ul>
</template>

<script>
import { mapMutations } from 'vuex'

export default {
computed: {
todos() {
return this.$store.state.todos.list
}
},
methods: {
addTodo(e) {
this.$store.commit('add', e.target.value)
e.target.value = ''
},
...mapMutations({
toggle: 'toggle'
})
}
}
</script>

<style>
.done {
text-decoration: line-through;
}
</style>


このコードでしっかりと動作・エラーが出ないことを確認します。


③TypeScriptで実装

上記のコードをTypeScriptで書くとこのようになります。


pages/index.vue

-- template内は上記コードと同様 --

<script lang="ts">
import { Vue, Component } from 'vue-property-decorator'
import { mapMutations } from 'vuex'

@Component({
methods: {
...mapMutations({ toggle: 'toggle' })
}
})
export default class extends Vue {
private get todos(): Object {
return this.$store.state.todos.list
}

addTodo(e): void {
this.$store.commit('add', e.target.value)
e.target.value = ''
}
}
</script>



TypeScriptでの変更点は以下です。


vue-property-decoratorの導入


methods

メソッドはクラスのメソッドになるため、 methods: {} の記述は不要です。


computed

computedは getter / setter で記述します。


map系ヘルパー(Vuex)

メソッドは上記のようにクラスのメソッドとして記述しますが、

...mapMutations を使う場合、@Component内にそのまま書きます

ちなみに、下記記事によるとmap系ヘルパーを使うと全てanyになってしまうため、TypeScriptで記述する恩恵が少ないみたいです。

Vuexによる状態管理を含む最高に快適な Vue.js + TypeScript の開発環境を目指す話 - Qiita

以上で、<script>から<script lang="ts">化ができました!

Vue(Nuxt)でTypeScriptを書く際は、すこしクセがあるのでJSとの違いがわかるVuexのコードを見たくて書きました。

ストアをTS化したらまた書きたいと思います。


参考資料

めちゃくちゃわかりやすいです

上記以外のTypeScriptの書き方が不明な方はこちらを参考に

* TypeScriptでVue.jsを書く – Vue CLIを使った開発のポイントを紹介 | maesblog

ストアをTS化するときに参考にしたいと思ってます

* VuexをTypeScriptで利用するのに悩んだ | cloudpack.media

クラスの書き方がわからないときはこちら

* vuejs/vue-class-component: ES / TypeScript decorator for class-style Vue components.

Vuexのmap系ヘルパーをどう使えば良いか悩みました

こちらを参考に@Component内に記述しました

* How to use ...mapGetters with class components? Typescript errors · Issue #109 · vuejs/vue-class-component