【初学者向け】Vue CLIを使ってTODOアプリを作る

# はじめに

### 作成するアプリについて

本記事ではVue CLIを使って、簡単なTODOアプリを作成していきます。
機能としては以下の通りです。

- TODO一覧の表示
- TODO追加
- TODO削除


![Untitled.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/d213dc24-cec7-df79-e61b-e7e999e3c828.gif)


対象読者
- progateのhtml, javascriptコースを完了した方
- Vue.jsを勉強し始めた方


### 参考文献

[Vue.jsでTodoアプリを作ってみよう](https://www.amazon.co.jp/Vue-js%E3%81%A7Todo%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86-kenpapa-ebook/dp/B07JLBB1V9)
kenpapa (著)



### 前提条件

以下がインストール済みであることを前提とします。

- Visual Studio Code
- node.js
- npm



# 目次
- Vue CLIのインストール
- プロジェクト作成
- サンプルアプリの起動
- TODO追加機能実装
    - 入力フォームの作成
    - TODOを格納する配列を定義
    - クリックイベントの実装
    - 追加処理の実装
    - TODOを一覧表示
    - チェック処理の実装

- TODO削除機能実装
    - クリックイベントの実装
    - 削除処理の実装



# Vue CLIのインストール

[Vue CLI](https://cli.vuejs.org/)とは、Vue.jsアプリケーションの雛形を簡単に作成できるツールです。
コマンドベースでサンプルアプリを作成できます。

では、Vue CLIをインストールしていきましょう。
Macであればターミナル、Windowsであればコマンドプロンプトを起動し、以下のコマンドを実行してください。

``` shell:
npm install -g @vue/cli
```


# プロジェクトの作成

Vue CLIのインストールが完了したら、プロジェクトを作成するディレクトリに移動してください。
今回はデスクトップ直下に"todo-app"というプロジェクト名で作成します。
ターミナルで以下コマンドを実行してください。

``` shell:
Desktop $ vue create todo-app
```

少し待つとプリセットの選択を求められます。
今回は追加で機能を設定できるManually select featuresを選択します。

``` shell:
Desktop $ vue create todo-app

Vue CLI v4.4.4
? Please pick a preset: 
  default (babel, eslint) 
❯ Manually select features 
```

デフォルトでBabelとLinter / Formatterにチェックが付いているかと思いますが、追加でRouterを選択します。
選択するにはカーソルを合わせてspaceキーを押下してください（Macの場合）
チェックがついたらEnterを押下してください。

``` shell:
? Please pick a preset: Manually select features
? Check the features needed for your project: 
 ◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
❯◉ Router
 ◯ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing
```

以降もいくつか選択を求められますが、全てデフォルトで大丈夫です。
全て選択するとプロジェクトの作成が始まります。

![スクリーンショット 2020-07-04 18.02.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/c95f2621-2079-144e-b441-82d2eaf2efa0.png)


プロジェクトの作成が完了すると以下の画面になります。
![スクリーンショット 2020-07-04 18.03.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/7cce611b-e350-230e-8f77-028a8f88457b.png)




















































# サンプルアプリの起動
それでは動作確認のためアプリを起動してみましょう。
cdコマンドでプロジェクトルートディレクトリに移動します。

``` shell:
Desktop $ cd todo-app
todo-app $ 
```

起動コマンドを叩きます。

``` shell:
todo-app $ npm run serve
```

起動コマンドを実行すると、ビルドが開始されます。
![スクリーンショット 2020-07-04 18.36.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/422764ea-c33b-488f-87b6-e297f3f3c9a0.png)

以下の画面が表示されれば、アプリの起動は完了です。
![スクリーンショット 2020-07-04 18.37.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/456d9e46-0c37-fde1-37ef-a81e22490905.png)

では、実際にアクセスしてみましょう。
任意のブラウザで[http://localhost:8080/](http://localhost:8080/)にアクセスしてください。
以下の画面が表示されるかと思います。
![スクリーンショット 2020-07-04 20.19.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/cad4f4e0-a787-d7d6-d07e-086bbe27a515.png)

これで動作確認は完了です。
アプリの起動を停止しましょう。
ctrl + cで停止させてください。
![スクリーンショット 2020-07-04 20.29.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/ff44d653-9c77-441f-735e-3bf72545313e.png)







### TODOアプリの確認
では、TODOアプリを作成していきましょう。
作成したプロジェクトをVisual Studio Codeで開いてください。
![スクリーンショット 2020-07-04 18.16.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/82cde214-4a2f-b57e-3a42-bb5b6f0b9e31.png)

App.vueを以下のように修正して、保存してください。

``` App.vue
<template>
  <div>
    <h3>My TODO</h3>
    <input v-model="newTodo" placeholder="Input here...">
    <button v-on:click="addTodo()">ADD</button>
    <h5>ToDo List</h5>
    <ul>
      <li v-for="(todo, i) in todos" v-bind:key="i">
        {{ todo }}
        <button v-on:click="deleteTodo(i)">DEL</button>
      </li>
    </ul>    
  </div>
</template>

<script>
export default {
  data() {
    return {
      todos: [],
      newTodo: ""
    }
  },
  methods: {
    addTodo() {
      if (this.newTodo === "") return;
      this.todos.push(this.newTodo);
      this.newTodo = "";
    },
    deleteTodo(i) {
      this.todos.splice(i, 1);
    }
  }
}
</script>
```

再度アプリを起動してみましょう。
また、Visual Studio Code内でターミナルを起動することも可能です。
上部メニューのターミナル>新しいターミナルから起動してください。

![スクリーンショット 2020-07-04 20.44.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/aa26e548-c230-384d-2ebf-c757ddfbe854.png)

起動コマンドは同じです。
![スクリーンショット 2020-07-04 20.44.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/b6c936b5-a7ac-e73e-b35c-afe59e943984.png)

起動後、再度"http://localhost:8080/"にアクセスしてください。
以下のような画面になっているかと思います。
![スクリーンショット 2020-07-04 20.57.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/a654c448-f158-82fe-092f-b7115e940855.png)

入力フォームに適当な値を入力して、ADDボタンを押してみてください。
![スクリーンショット 2020-07-04 20.59.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/f9657c86-8e3d-7c47-a345-ea9d6793c92a.png)

ToDo Listに項目が追加されるかと思います。
![スクリーンショット 2020-07-04 21.03.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639403/0e95e3b2-5b8d-9d16-51ea-7df66f4d25f6.png)


こちらが今回作成するアプリになります。
ここではアプリのイメージを掴むため、コピペしていただきましたが、以降では順を追って実装内容を説明していきます。
初学者の方は、App.vueの記載を全て削除して、一から自身でコーディングしてみることをおすすめします。















# TODO追加機能の実装
では、実装内容を見ていきましょう。
一からコーディングされる方向けに説明していきます。

まず、App.vueの記載を全て削除し、以下のようにベース部分をコーディングしましょう。
機能は何もありませんが、起動すると静的な画面が表示されます。

``` vue:App.vue
<template>
  <div>
    <h3>My TODO</h3>
    <input placeholder="Input here...">
    <button >ADD</button>
    <h5>ToDo List</h5>
    <ul>
      <li>
      </li>
    </ul>    
  </div>
</template>

<script>
export default {
  data() {
    return {

    }
  },
  methods: {

  }
}
</script>
```

### 入力フォームの作成
TODOを追加するには、input要素に入力された値をjavascript側で操作できるようにする必要があります。
Vue.jsではその紐付けのことをバインディングと呼んでいます。
input要素に入力された値をバインディングするには、v-modelディレクティブを使用します。

[v-modelディレクティブについては、こちらを参照してください](https://jp.vuejs.org/v2/guide/forms.html)

ここでは変数名をnewtodoとしています。

``` vue:template部分
<input v-model="newTodo" placeholder="Input here...">
```

合わせてscript部分のdataに変数newtodoを定義します。
return{}のなかに記載してください。
これで"newtodo"という変数のバインディングを定義したことになります。

``` js:data()部分
data() {
  return {
    newTodo: ""
 }
}
```

上記のように記載すると、input要素に入力された値をjavascript側で、"newTodo"という変数名で扱えるようになります。


### TODOを格納する配列を定義
次にTODOの格納先を作成します。
今回は簡易的に配列に格納することにします。
Script部分のdata()にtodosという変数名で、空の配列を定義してください。
カンマ","を忘れないよう注意してください。

``` js:data()部分
data() {
  return {
    todos: [],
    newTodo: ""
 }
}
```
todosという変数とnewTodoという変数を定義したことになります。


### クリックイベントの実装
TODOの追加方法ですが、ADDボタンが押されたら、配列に追加する仕様としましょう。
※このような仕様を説明する際は、ボタンのクリックイベントをトリガーにTODOの追加処理を行う、などと言います。

Vueでクリックイベントの実装には、v-onディレクティブを使用します。
ここではクリック時にaddTodo()メソッドを実行するよう定義しています。

``` vue:template部分
<button v-on:click="addTodo()">ADD</button>
```

### 追加処理の実装
続いて、追加処理となるaddTodo()メソッドを定義します。
Vue.jsではmethods部分にメソッドを定義していきます。

``` js:methods部分
methods: {
  addTodo() {
    this.todos.push(this.newTodo);
    this.newTodo = "";
  }
}
```

まず、配列に追加する値を取得します。
data部分に定義された変数を呼び出すにはthisを使います。
this.newTodo でフォームに入力された値を取得することができます。
また、格納先の配列もthisを使って記載します。

追加処理は引数の値を配列に格納するpushメソッドを使用します。
以下のような実装をすることで、追加処理を行なっています。

```
this.配列の変数名.push(this.追加対象の変数名)
```

また、追加処理後に変数newTodoの値を空に設定します。
入力フォームの値をクリアしています。

```
this.newTodo = "";
```

※上記で説明したバインディングは、正確には双方向バインディングという機能です。
詳細は[こちら](https://jp.vuejs.org/v2/guide/forms.html)を参照してください



### TODOの一覧表示
追加したTODOを一覧表示する機能を実装していきます。
方針としては配列に格納された値を取得し、繰り返し処理を実施して、各項目を表示していきます。
Vue.jsで繰り返し処理を行うには、v-forディレクティブを使用します。
templateのli要素の部分を修正してください。

``` vue:template部分
<li v-for="(todo, i) in todos" v-bind:key="i">
  {{ todo }}
</li>
```

``` v-for="(todo, i) in todos" ```と書くことで、配列todosから要素を１つ１つ取得し、todoという変数に格納しています。
``` {{ todo }} ```で変数todoに格納された値を表示しています。
``` v-bind:key="i" ```ではindex番号を格納する変数を定義しています。こちらは削除処理の際に、対象要素を指定するのに使用します。


### チェック処理の実装
ここまででTODOの追加処理を実装することができました。
しかし、入力フォームが空のままADDボタンを押して見てください。
TODO名が空の項目が追加されていると思います。
これは本来の用途に沿わないため、仕様として不適切です。

これを回避するためチェック処理を実装します。
pushメソッドを実行する前に、以下のif文を追加してください。

``` js:methods部分
methods: {
  addTodo() {
    if (this.newTodo === "") return;
    this.todos.push(this.newTodo);
    this.newTodo = "";
  }
}
```

this.newTodoの値が空の場合、addTodoメソッドを抜ける（returnする）処理を実装しています。



# TODO削除機能の実装説明
### クリックイベントの実装
追加と同様にv-onディレクティブを使用して、DELボタン押下をトリガーに、TODOを削除する仕様とします。
メソッド名deleteTodo(i)メソッド
引数の```i```はindex番号が格納されています。

``` vue:template部分
<li v-for="(todo, i) in todos" v-bind:key="i">
  {{ todo }}
  <button v-on:click="deleteTodo(i)">DEL</button>
</li>
```

### 削除処理の実装
methodsにdeleteTodoメソッドを実装します。
配列から要素を削除するには、spliceメソッドを使用します。

spliceメソッドは第一引数で開始位置を指定し、第二引数で削除する要素の個数を指定します。
[spliceメソッドの説明](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/splice)

開始位置はインデックス番号と同じですので、第一引数には```i```を指定し、削除個数は1要素だけですので、第二引数には```1```を指定します。


``` js:methods部分
  methods: {
    addTodo() {
      if (this.newTodo === "") return;
      this.todos.push(this.newTodo);
      this.newTodo = "";
    },
    deleteTodo(i) {
      this.todos.splice(i, 1);
    }
  }
```

これで一通りのTODO追加、削除機能が実装できました。

# 終わりに

お疲れ様でした。
次回はデータベースやAPIサーバを利用した実装を紹介したいと思います。