Vue.js 入門（第４回【最終回】） - ToDoリストを作ってみる -

# はじめに

`Vue.js`に少し触れてみたので、その内容を「**Vue.js入門**」として、数回にわけて書いてきました。
今回の４回目（最終回）では「ToDoリスト」を作ってみました。
前の記事は以下を参照してください。

+ [Vue.js 入門（第１回） - Vue.jsでHello World と双方向データバインディング（v-model） -](https://qiita.com/yasushi-jp/items/b5226a5379b3539da81b "Vue.js 入門（第１回） - Vue.jsでHello World と双方向データバインディング（v-model） -")
+ [Vue.js 入門（第２回） - 算出プロパティ（computed）と監視（watch） -](https://qiita.com/yasushi-jp/items/5f4e6c6a5eb0284cab15 "Vue.js 入門（第２回） - 算出プロパティ（computed）と監視（watch） -")
+ [Vue.js 入門（第３回） - メソッド（methods） -](https://qiita.com/yasushi-jp/items/52f4b77f2ec2a8d9c15c "Vue.js 入門（第３回） - メソッド（methods） -")

※ここではVue.jsの**2.x系（2.6.14）**を使用しています。**3.x系**では書き方が異なるので注意してください。

# 1. 作成するToDoリストの仕様

初期表示で以下の通り表示します。
①はToDoの入力欄で、②はToDoリストの表示欄です。
![4-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/68afda00-4ecb-b47f-8eb7-1eb7a43f83b1.png)

入力欄にToDoの名前を入力し（①）、「追加」ボタンをクリックします（②）。
すると、ToDoの入力欄がクリアされ（③）、ToDoリストに入力したToDoが追加されます（④）。
![4-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/d2aadbbb-6335-a606-bf7e-29217d455396.png)
![4-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/c47e93f1-8dbf-26a0-8843-64ea22011023.png)

ToDoリストのチェックボックスをオンにすると、ToDoの名前の前に「完了」を表示します。
![4-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/c9f8d214-52a1-0f57-bf3e-89382ed65c6b.png)

ToDoリストの「削除」ボタンをクリックすると（①）、ToDoリストの一覧から削除されます（②）。
![4-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/d2f64b87-919b-4eeb-32e0-cfcdb8a82f46.png)
![4-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292434/943a5e70-e42e-cd57-2665-e78f96e0888d.png)

# 2. ToDoリスト作成
### 2.1. jsの作成

```js:js/main.js
var vm = new Vue({
  el: '#app',   // （１）
  data: {
    todos: [    // （２）
      {isDone: false, name: 'Task1'},
      {isDone: false, name: 'Task2'},
      {isDone: false, name: 'Task3'}
    ],
    input: ''   // （３）
  },
  methods: {
    addTodo: function(input) {    // （４）
      var todo = {                // （５）
        isDone: false,
        name: input
      };
      this.todos.push(todo)       // （６）
      this.input = '';            // （７）
    },
    deleteTodo: function(index) { // （８）
      this.todos.splice(index, 1) // （９）
    }
  }
});
```

（１）`el`の名称を`app`として、HTMLの&lt;div&gt;と紐付けます。
（２）`data`に変数`todos`を定義し、配列を保持します。`todos`は`isDone`（チェックボックスをチェックしているかどうかを保持する変数）と`name`（ToDoの名称を保持する変数）のセットの配列としています。HTMLのToDoリストと紐付けます。
（３）`data`に変数`input`を定義します。HTMLのToDoの入力欄と紐付けます。
（４）`methods`に`addTodo`を定義します。HTMLの追加ボタンをクリックしたときに呼び出されます。
（５）変数`todo`を定義し、`isDone`は初期値falseを設定、`name`には`input`（入力されたToDoの名称）を設定します。
（６）`todos`（ToDoリスト）に（５）の`todo`を追加します。
（７）`input`（ToDoの名称の入力欄）に空文字を設定します。
（８）`methods`に`deleteTodo`を定義します。HTMLの削除ボタンをクリックしたときに呼び出されます。
（９）`todos`（ToDoリスト）から該当の行を削除します。

### 2.2. HTMLの作成

```html:index.html
<!DOCTYPE html>
<html lang="jp">
  <head>
    <meta charset="utf-8">
    <title>Vue.jsでToDoリスト</title>
    <link rel="stylesheet" href="css/main.css">
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
  </head>
  <body>
    <div id="app">      <!-- （１） -->
      <h1>ToDoリスト</h1>
      <span>ToDo：</span>
      <input type="text" v-model="input">   <!-- （２） -->
      <button type="button" v-on:click="addTodo(input)">追加</button> <!-- （３） -->
      <ul>
        <li v-for="(todo, index) in todos"> <!-- （４） -->
          <div>
            <input type="checkbox" v-model="todo.isDone">                       <!-- （５） -->
            <span class="done" v-show="todo.isDone">完了</span>                 <!-- （６） -->
            <span>{{ todo.name }}</span>                                        <!-- （７） -->
            <button type="button" v-on:click="deleteTodo(index)">削除</button>  <!-- （８） -->
          </div>
        </li>
      </ul>

    </div>
    <script src="js/main.js"></script>
  </body>
</html>
```

（１）`id=app`として、`Vue`のインスタンスと紐付けます。
（２）`v-model="input"`として、`input`変数と紐付けます。
（３）`v-on:click="addTodo(input)"`で、押下時に`addTodo`メソッドを呼び出すようにします。
（４）`v-for="(todo, index) in todos"`として、`todos`変数の件数分繰り返します。`todo`に`todos`の1件分のデータを、`index`に繰り返しのインデックスがセットされます。
（５）`v-model="todo.isDone"`で、`isDone`変数と紐付けます。
（６）`v-show="todo.isDone"`で、`isDone`変数が`true`の場合のみ表示させます。
（７）`name`を表示させます。
（８）`v-on:click="deleteTodo(index)"`で、押下時に`deleteTodo`メソッドを呼び出すようにします。

### 2.3. CSSの作成

今回は以下のCSSを定義しています。

```css:css/main.css
ul,
li {
  margin: 0 0 6px 0;
  padding: 0;
  list-style: none;
}

ul {
  margin-top: 30px;
}

 li div {
  position: relative;
  max-width: 300px;
  width: 100%;
  padding-right: 0px;
  box-sizing: border-box;
  white-space: break-all;
}

li button {
  position: absolute;
   top: 0;
  right: 0;
}

.done {
  color: #F00;
}
```

# 参考
+ [Vue.js](https://jp.vuejs.org/ "Vue.js")
+ [とほほのVue.js入門](https://www.tohoho-web.com/ex/vuejs.html "とほほのVue.js入門")

# リンク
+ [Vue.js 入門（第１回） - Vue.jsでHello World と双方向データバインディング（v-model） -](https://qiita.com/yasushi-jp/items/b5226a5379b3539da81b "Vue.js 入門（第１回） - Vue.jsでHello World と双方向データバインディング（v-model） -")
+ [Vue.js 入門（第２回） - 算出プロパティ（computed）と監視（watch） -](https://qiita.com/yasushi-jp/items/5f4e6c6a5eb0284cab15 "Vue.js 入門（第２回） - 算出プロパティ（computed）と監視（watch） -")
+ [Vue.js 入門（第３回） - メソッド（methods） -](https://qiita.com/yasushi-jp/items/52f4b77f2ec2a8d9c15c "Vue.js 入門（第３回） - メソッド（methods） -")