TypeScript,NuxtでTodoアプリ作ってみる

2019/04/11

NuxtでTypeScriptでTodoアプリを作ってみます。
(Vuex普通のjsになってます。)

まずはstoreを作ります。
stateとしてlist、
mutationとして、addTodoでlistを追加、deleteTodoで選択したTodoを削除するstoreです。

store/index.ts

import {Module, VuexModule, Mutation} from 'vuex-module-decorators'

@Module
export default class Todo extends VuexModule {
  public list: { title: string; }[] = [];

  @Mutation
  addTodo(val: string) {
    this.list.push({
      title: val
    })
  }
}

次にとりあえず普通のJavaScriptでVueコンポーネントを書いてみます。
computed
todoListをstoreのlistと同期

methods
addItemで入力されていたものをstoreにcommitしてstoreで追加
(何も入力されたいなかった場合はalertだす)
deleteItemで選択されてもののindexをstoreにcommmitしてstoreで削除

<template>
  <div>
    <input v-model="todoInput" placeholder="入力してください">
    <button @click="addItem">追加!</button>
    <ul>
      <li v-for="(item,index) in todoList" :key=index>
        {{item.title}}
        <button @click="deleteItem(index)">削除</button>
      </li>
    </ul>
  </div>
</template>

<script>
  import {mapMutations} from 'vuex'

  export default {
    data() {
      return {
        todoInput: ''
      }
    },
    computed: {
      todoList() {
        return this.$store.state.list;
      }
    },
    methods: {
      addItem() {
        if (this.todoInput) {
          this.$store.commit('addTodo', this.todoInput)
        } else {
          alert('入力してください')
        }
      },
      deleteItem(index) {
        this.$store.commit('deleteTodo', index)
      }
    }
  }

</script>

これをTypeScriptで書いてみます。
TypeScriptで書くに当たって、vue-property-decoratorを使用します。
これを使用することでTypeScriptのクラス構文でVueを書くことができます。

computedはget/setアクセサ
methodsはクラスのメソッド
dataはクラスのプロパティ
として書きます。

<template>
  <div>
    <input v-model="todoInput" placeholder="入力してください">
    <button @click="addItem">追加!</button>
    <ul>
      <li v-for="(item,index) in todoList" :key=index>
        {{item.title}}
        <button @click="deleteItem(index)">削除</button>
      </li>
    </ul>
  </div>
</template>

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

  @Component
  export default class index extends Vue {
    private todoInput:string = '';
    get todoList(): { title: string;}[] {
      return this.$store.state.list;
    }

    @Emit()
    addItem(): void {
      if(this.todoInput) {
        this.$store.commit('addTodo', this.todoInput)
      } else {
        alert('入力してください')
      }
    }
    deleteItem(index:number):void {
      this.$store.commit('deleteTodo',index)
    }
  }

</script>