Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

簡単に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

su_mi1228
フロントエンドエンジニア初心者です JavaScriptが好きです(できるわけではない) 日々勉強しながら業務しています〜!
yumemi
みんなが知ってるあのサービス、実はゆめみが作ってます。スマホアプリ/Webサービスの企画・UX/UI設計、開発運用。Swift, Kotlin, PHP, Vue.js, React.js, Node.js, AWS等エンジニア・クリエイターの会社です。東京(三軒茶屋)/京都(四条烏丸)/札幌/大阪/福岡に展開中!Twitterで情報配信中https://twitter.com/yumemiinc
http://www.yumemi.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした