[チュートリアル] commitを追いながらVue.jsでtodoアプリを作成してherokuにデプロイしてみる

おもにバックエンド側を触ることが多いのですが、フロント側も覚えたいなと思い最近Vue.jsに入門しました。

[Vue.js公式のドキュメント](https://jp.vuejs.org/)は日本語訳されており、[公式のサンプル](https://jp.vuejs.org/v2/examples/)もいくつかあるのですが、
さあこれから始めよう！と思う初心者には環境構築を含めてちょっとハードルが高い気がしました。
（私が調べた限り日本語で良さそうなチュートリアルはありませんでした。）

そこで今回は自分で[TODOアプリをVue.jsで0からつくる手順を公開しているサイト](https://scotch.io/tutorials/build-a-to-do-app-with-vue-js-2) （英語）を参考にして、
TODOアプリを作成してherokuにデプロイするまでやってみたので、GitHubのcommitを追いながら簡単に解説をしてみたいと思います。

実際の動作は以下から確認できます。

https://vue-todo-app.herokuapp.com/

GitHubのリポジトリはこちらです。

https://github.com/tackeyy/vue-todo-app

とくに関係ないですが、私のブログはこちらです。

http://tackeyy.com/

# 今回スコープ外のはなし

- ルーティング / vue-router2
- 状態管理・データ永続化 / Vuex 
- テスト

# こんな人におすすめ

- ある程度Vue.jsの雰囲気はわかったので簡単なVueアプリをつくってみたい人
- vue-cliで作ったアプリをherokuにデプロイしてみたい人

# 環境

` vue-cli 2.8.1 `

※ 2017/06/28時点では ` vue-cli 2.8.2 ` がリリースされています

# vue-cliのインストール

vue-cliはVue.jsを使う環境のテンプレートを用意してくれるコマンドラインツールです。
自分で環境を作るのは面倒なのでvue-cliを使って進めていきます。
たとえば ` $ vue init webpack my-project ` するだけでWebpack + vue-loader ホットリロードの環境が出来上がります。

https://jp.vuejs.org/2015/12/28/vue-cli/

# プロジェクト作成

プロジェクトを作成するディレクトリに移動してから以下のコマンドでプロジェクトを作成します。
` vue-todo-app ` はアプリ名なのでお好きなものに変更しても構いません。

` $ vue init webpack vue-todo-app `

今回はrouterとtestは説明しないのでvue-cliからの質問に以下のように答えてください。
（全部Yesでも特に問題はありません）

```
? Project name vue-todo-app
? Project description A Vue.js project
? Author tackeyy
? Vue build standalone
? Install vue-router? No
? Use ESLint to lint your code? Yes
? Pick an ESLint preset Standard
? Setup unit tests with Karma + Mocha? No
? Setup e2e tests with Nightwatch? No
```

プロジェクトができたら以下のコマンドを実行してアプリを起動します。

` $ cd vue-todo-app `
` $ npm install `
` $ npm run dev `

` $ npm run dev ` をすると自動的にブラウザが開きます。

[![https://gyazo.com/a4ec0994833f1803cac44b61298fcc3f](https://i.gyazo.com/a4ec0994833f1803cac44b61298fcc3f.png)](https://gyazo.com/a4ec0994833f1803cac44b61298fcc3f)

# Todo listを作成する

https://github.com/tackeyy/vue-todo-app/commit/39dc13b8ef2c36b92e315874786b99ac9c2d5455

## コミットの内容

- デフォルトで入っている ` Hello.vue ` とそれに関連する記述を削除
- ` src/components/TodoList.vue ` でTodoリストを作成
- Todoリストを[src/App.vue](https://github.com/tackeyy/vue-todo-app/commit/39dc13b8ef2c36b92e315874786b99ac9c2d5455#diff-ea994a51b0d9884f4fc046eca11a5c99)で読み込み

# TODOを表示する

https://github.com/tackeyy/vue-todo-app/commit/36b14ed0c2dd33b4e542e2be996a2c2bcd0c2485

## コミットの内容

- [src/App.vue](https://github.com/tackeyy/vue-todo-app/commit/36b14ed0c2dd33b4e542e2be996a2c2bcd0c2485#diff-ea994a51b0d9884f4fc046eca11a5c99R15)で表示するTODOの初期データを定義
- [src/components/TodoList.vue](https://github.com/tackeyy/vue-todo-app/commit/36b14ed0c2dd33b4e542e2be996a2c2bcd0c2485#diff-2421d7da8243befe4efecb03d5b23d61)でTODOの初期データを表示
- [src/App.vue](https://github.com/tackeyy/vue-todo-app/commit/36b14ed0c2dd33b4e542e2be996a2c2bcd0c2485#diff-ea994a51b0d9884f4fc046eca11a5c99R3)で ` TodoList.vue ` のテンプレートを呼び出し
- 見た目を整えるためにSemantic UIを[ここで](https://github.com/tackeyy/vue-todo-app/commit/36b14ed0c2dd33b4e542e2be996a2c2bcd0c2485#diff-eacf331f0ffc35d4b482f1d15a887d3bR5)使っています

## 使用されているVue.jsの文法

```
<todo-list v-bind:todos="todos"></todo-list>
```

` TodoList.vue ` に ` todos ` を渡しています。
` TodoList.vue ` で ` props: ['todos'] ` とすることで、渡した ` todos ` を ` TodoList.vue ` で使用できるようになります。

データの受け渡しについてもう少し理解を深めたい場合は、[[図解]Vue.js2.x系で親子コンポーネント間でデータの受け渡しをする方法](http://kuroeveryday.blogspot.jp/2016/10/vuejs-components-emit-events.html)がわかりやすかったので目を通してみてください。

今回は省略記法を用いていませんが、 ` v-bind ` には省略記法があり、以下のようにも書くことができます。
https://jp.vuejs.org/v2/guide/syntax.html#v-bind-省略記法

```
<!-- 完全な構文 -->
<a v-bind:href="url"></a>
<!-- 省略記法 -->
<a :href="url"></a>
```

```
<div class='ui centered card' v-for="todo in todos">
```

ある程度予測がつきますが、 ` v-for ` はfor文と同じです。
https://jp.vuejs.org/v2/guide/list.html#v-for

```
<p class="tasks">完了したタスク: {{ todos.filter(todo => { return todo.done === true }).length }}</p>
```

` filter ` はVue.jsの機能です。完了したTODOの数を取得しています。
今見返すと、 ` todo.done === true ` と書かなくても良いですね。

```
{{ todos.filter(todo => { return todo.done }).length }}
```

https://jp.vuejs.org/v2/guide/list.html#配列の置き換え


```
<div class='ui bottom attached green basic button' v-show="todo.done">
```

` v-show ` の右辺が真の場合は要素を表示します。
条件付きレンダリングでは ` v-if ` という似たような機能があります。

` v-show ` はレンダリングしたものを ` display ` CSSプロパティで切り替えるのに対して、 ` v-if ` は条件が真だった場合に初めてレンダリングされるという違いがあります。

Vue.jsのドキュメントにも以下のようにあります。

> とても頻繁に何かを切り替える必要があれば v-show を選び、条件が実行時に変更することがほとんどない場合は、v-if を選びます。

https://jp.vuejs.org/v2/guide/conditional.html#v-else

今回のケースではtodoの状態はぼちぼち変わることから、 ` v-show ` で良いのかなと思います。


# TODOの編集

https://github.com/tackeyy/vue-todo-app/commit/c8c05328968a4a1cb23717cef3b6a4125d8f32ec

## コミットの内容

- ` TodoList.vue ` に記載していたTODOを1つのコンポートネント（ [Todo.vue](https://github.com/tackeyy/vue-todo-app/commit/c8c05328968a4a1cb23717cef3b6a4125d8f32ec#diff-db31af0b41b321305d657ed9fd367443) ）にしています

## 使用されているVue.jsの文法

` <span class='right floated edit icon' v-on:click="showForm"> `

DOMイベントの購読してイベント発火できます。
上記の要素をクリックすると[showForm](https://github.com/tackeyy/vue-todo-app/commit/c8c05328968a4a1cb23717cef3b6a4125d8f32ec#diff-db31af0b41b321305d657ed9fd367443R51)が呼ばれます。

https://jp.vuejs.org/v2/guide/events.html


# TODOの削除

https://github.com/tackeyy/vue-todo-app/commit/49bd51d11c7d566e04ab1cc975239e2e2962c95c

## コミットの内容

- ゴミ箱アイコンをクリックするとTODOを削除できるようにしています

## 使用されているVue.jsの文法

` <todo v-on:delete-todo="deleteTodo" ... </todo> `

```
+      deleteTodo(todo) {
+        this.$emit('delete-todo', todo)
+      },
```

` Todo.vue ` の親コンポーネント（ ` TodoList.vue ` ）の ` delete-todo ` で発火する ` deleteTodo ` 関数を呼び出しています。第二引数の ` todo ` は削除されるTODO自身です。

https://jp.vuejs.org/v2/api/#vm-emit


# [SweetAlert](http://t4t5.github.io/sweetalert/)の導入

https://github.com/tackeyy/vue-todo-app/commit/8c4373120b437ec0136cdecf06e34495b6ca8a35

## SweetAlert

いい感じのダイアログを出せるライブラリです。
本家のページで動作感が確認できます。

http://t4t5.github.io/sweetalert/

## コミットの内容

- SweetAlertで必要なjs, cssをCDN経由で取得
- [ここらへん](https://github.com/tackeyy/vue-todo-app/commit/8c4373120b437ec0136cdecf06e34495b6ca8a35#diff-2421d7da8243befe4efecb03d5b23d61R20)でSweetAlertを使用してアラートを出すように修正

# TODOの作成

https://github.com/tackeyy/vue-todo-app/commit/a44ea7e7126af0e2937922cd22998ad43a5b0a85

## コミットの内容

- [CreateTodo.vue](CreateTodo.vue)というコンポーネントを追加して、新しいTODOを作成できるようにしています

## 使用されているVue.jsの文法

今まで説明した文法だけなので特に説明はありません。

# TODOを完了にする

https://github.com/tackeyy/vue-todo-app/commit/51559fe45955d19c3c3ba3af1996868179a62001

## コミットの内容

- PendingをクリックするとCompletedに変わるようにしています

## 使用されているVue.jsの文法

ここも今まで出てきた文法だけで事足ります。

# Herokuにデプロイ

https://github.com/tackeyy/vue-todo-app/commit/1252239921600a891ed1534ea3bc1b7b0c31af65

TODO: heroku側の設定、heroku-cliの導入、コミットの説明

（´-`）.｡oO（追記して欲しい方がもし入れば追記しますのでコメントください)

# さいごに

説明が足りない部分や勘違いがあればぜひコメント等で優しく教えていただけると助かります。
もっとシンプルにかけるよ、などの指摘やプルリクなども歓迎ですー！

# 参考にした記事

https://scotch.io/tutorials/build-a-to-do-app-with-vue-js-2
http://www.travisluong.com/how-to-deploy-a-vue-js-app-to-heroku/
https://medium.com/@sagarjauhari/quick-n-dirty-way-to-deploying-vue-webpack-apps-on-heroku-4ab964ee536