Vue.jsでTO DOアプリを作る

## はじめに

[Vue.jsの基本的な使い方まとめ](https://qiita.com/yukiji/items/862b8dd91dc410259fb4)の続きです。

チュートリアルの鉄板であるTO DOアプリを作成していきます。

## テンプレートを用意する

雛形となるHTMLとJSを作成します。

`todo`ディレクトリを作成して、その中に`index.html`と`index.js`を作成します。

```html:todo/index.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>TO DOアプリ</title>
    </head>
    <body>
        <div id="app">
          <!-- ここにVueインスタンスを展開する -->
        </div>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
        <script src="./index.js"></script>
    </body>
</html>
```

続いてVueインスタンスを作成する。

```js:todo/index.js
var app = new Vue({
  el: '#app'
})
```

## 入力フォームとメソッドの追加

`form`要素の中に入力フォームとボタンを追加する。

```html
<div id="app">
    <h2>TODO List</h2>
    <form>
        <input type="text">
        <button>
          追加
        </button>
    </form>
</div>
```

続いて`button`要素に`v-on:click`を設定する。

buttonがクリックされたら`addItem`メソッドを呼び出す。

```html
<button v-on:click="addItem">
```

Vueインスタンスに`addItem`メソッドを記述する。

一旦、正常に動いているか確認するため、アラートを表示させてみる。

```js
var app = new Vue({
  el: '#app',
  // メソッド定義
  methods: {
    addItem: function(event) {
      alert()
    }
  }
})
```

次に`button`をクリックした時に`submit`イベントが発動して、ページがリロードされるのを防ぐ処理を`form`に記述する。

`prevent`はデフォルトの動作を停止させる。

```html
<form v-on:submit.prevent>
```

## TO DOリストにタスクを登録

input要素に`v-model`を記述して双方向データバインディング出来るようにする。

これで、inputに入力した値がdataオプションで定義するプロパティと同期する。

```html
<!-- v-modelを定義 -->
<input type="text" v-model="newItem">
```

dataオプションに`newItem`と、入力した値(todoのタスク)を保存する配列`todo`を定義する。

```js
var app = new Vue({
  el: '#app',
  data: {
    newItem: '', // 入力フォームと双方向データバインディング
    todos: [] // 入力したtodoを保存する配列
  },
  methods: {
    addItem: function(event) {
      alert()
    }
  }
})
```

さらに、入力フォームで入力した値を配列に保存できるように`addItem`メソッドを書き換える。

プロパティには`this.プロパティ名`でアクセスできる。

この`this`はVueインスタンスを指す。

```js
var app = new Vue({
  el: '#app',
  data: {
    newItem: '',
    todos: []
  },
  methods: {
    addItem: function(event) {
      var todo = {
        item: this.newItem // todoオブジェクトに入力した値を保存
      }
      this.todos.push(todo) // todoを配列に追加
    }
  }
})
```

## TO DOリストの改善

`button`をクリックしてタスクを追加した後に、inputに文字列が残ってしまうため、文字列をクリアにする記述をする。

さらに、空の文字列を保存するのを防ぐための処理を記述する。

```js
methods: {
    addItem: function(event) {
      // 追加
      if (this.newItem === '') return // 空の文字列の場合はここで処理を終える
      var todo = {
        item: this.newItem
      }
      this.todos.push(todo)
      // 追加
      this.newItem = '' // 入力フォームの文字列をクリア
    }
```

## TO DOリストの表示

HTML側でリスト表示させる記述をする。

`v-for`ディレクィブを使って繰り返し処理をする。

```html
<div id="app">
    <h2>TODO List</h2>
    <form v-on:submit.prevent>
        <input type="text" v-model="newItem">
        <button v-on:click="addItem">
          追加
        </button>
    </form>
    <!-- 追記 -->
    <ul>
        <li v-for="todo in todos">
            {{ todo.item }}
        </li>
    </ul>
    <!-- 追記 -->
</div>
```

## タスクの完了と未完了の実装

タスクの完了と未完了を管理するチェックボックスを設定する。

`addItme`メソッドの変数`todo`を編集する。

チェック済みかどうか判定する`isDone`を追加し、初期値を`false`に設定する。

```js
var todo = {
  item: this.newItem,
  isDone: false // 追加
  }
```

次に、HTMlにチェックボックスを追加し、`v-model`ディレクティブに`todo.isDone`を双方向データバインディングさせる。

これで、チェックされると`isDone`が`true`になる。

```html
<ul>
    <li v-for="todo in todos">
        <input type="checkbox" v-model="todo.isDone">
        <span>{{ todo.item }}</span>
    </li>
</ul>
```

## タスクの削除を実装

登録したタスクを個別に削除するため、配列の`index`を取得する。

`v-for="(値, index) in 配列"`で配列の`index`が取れる。

続いて削除ボタンを追加し、タスクを削除するメソッド`deleteItem`を定義する。

`deleteItem`メソッドの引数には配列の`index`を持たせる。

```html
<ul>
    <li v-for="(todo, index) in todos"> <!-- indexの取得 -->
        <input type="checkbox" v-model="todo.isDone">
        <span>{{ todo.item }}</span>
        <!-- 追加 -->
        <button v-on:click="deleteItem(index)">Delete</button> 
    </li>
</ul>
```

続いて`deleteItem`メソッドを定義する。

配列から要素を削除するJavaScriptの`splice`メソッドを使用して、登録されたタスクを削除する。

```js
methods: {
    addItem: function(event) {
    // 〜省略〜
    },
    //追加
    deleteItem(index) {
      this.todos.splice(index, 1) // sprice(削除を始めるindex, 削除する長さ)
    }
  }
```

## まとめ

DOMの取得やデータの更新を意識することなく書けるので、コードの見通しがスッキリする。

そして、データバインディング楽しい:v:

## 更新履歴

:zap:[Vue.jsの基本的な使い方まとめ](https://qiita.com/yukiji/items/862b8dd91dc410259fb4)
:zap:[Vue.jsでTO DOアプリを作る](https://qiita.com/yukiji/items/dc45f45f7f3f0e53f626) :point_left:今ココ
:zap:[Vue.js テンプレート制御ディレクティブ まとめ](https://qiita.com/yukiji/items/a77dd6d8dd0f194770c3)
:zap:[Vue.js 算出プロパティとメソッドの違い](https://qiita.com/yukiji/items/525469503cdba334658e)