【Vue.js初心者】Todoリストはこう作る！～Todo追加～

#概要
以下のVue.js公式で紹介されているサンプルについてどのように動作しているのか見ていきます。
https://jp.vuejs.org/v2/examples/todomvc.html

jsfiddleでも見れるので実際に触りながら見てみましょう。
https://jsfiddle.net/yyx990803/4dr2fLb7/?utm_source=website&utm_medium=embed&utm_campaign=4dr2fLb7

こんな感じの画面構成です。
![サンプル画面01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251494/c81ebf67-cdd5-375a-d0b8-1511a258f270.png)

# この記事の対象読者
・Vue.jsの公式ドキュメントに一通り目を通している
・でもまだよくわかっていない
・私もそうです


# 機能概要
以下の機能が存在します。
・TODO追加
・TODO削除
・TODO完了
・完了済みTODO件数表示
・TODOフィルター
・完了済みTODO全削除

ひとつずつ見ていきましょう。

# TODO追加
#### ・まずは入力欄を見てみる

この例では入力欄に文字列を入力し、Enterを押下するとTODOリストに追加されます。
これはどのように行っているのでしょうか？

```html:HTML
    <input class="new-todo"
      autofocus autocomplete="off"
      placeholder="What needs to be done?"
      v-model="newTodo"
      @keyup.enter="addTodo">
```

このあたりが入力欄の部品のようです。

```html
   @keyup.enter="addTodo" 
```

というのはENTERボタンを押したのち離した際に、JavaScriptのメソッド「addTodo」を呼び出します。[^1]
ちなみに「@」はv-on:の省略形なので今回の場合、

```html
v-on:keyup.enter="addTodo"
```

と書いても同様です。[^2]

さて、呼び出されるJavaScriptのメソッド「addTodo」は

```javascript:JavaScript
  methods: {
    addTodo: function () {
      var value = this.newTodo && this.newTodo.trim()
      if (!value) {
        return
      }
      this.todos.push({
        id: todoStorage.uid++,
        title: value,
        completed: false
      })
      this.newTodo = ''
    },
```
methods内にありました。

#### ・addTodoメソッド

何をやっているかというと、
this.newTodo と this.newTodo.trim() をAND条件で真偽値を取得しています。(value)

this.newTodo は data内に定義してありますね。

```javascript:JavaScript
  data: {
    todos: todoStorage.fetch(),
    newTodo: '',
    editedTodo: null,
    visibility: 'all'
  },
```
this.newTodo.trim() は this.newTodoをトリム(空白スペースを除く)を行っています。

ですが、data内で定義されたnewTodoは''(空文字)が設定されています。
ここ以外でnewTodoに値が設定される記述があるはず。

```html:HTML
    <input class="new-todo"
      autofocus autocomplete="off"
      placeholder="What needs to be done?"
      v-model="newTodo"
      @keyup.enter="addTodo">
```
ここだ。先ほども出てきたinputタグですが、ここで

```html
    v-model="newTodo"
```

と記述していますね。v-modelとはユーザが入力した値をdataに設定するためのディレクティブです。[^3]
ディレクティブとはVue.jsに何らかの指示を行う仕組みのことです。

つまり、入力欄にスペースが入力されている、または入力がない場合、処理を行わずreturnする、と読み取れます。
addTodoの続きを見ていきましょう。

```javascript:JavaScript
  methods: {
    addTodo: function () {
      //省略
      this.todos.push({
        id: todoStorage.uid++,
        title: value,
        completed: false
      })
      this.newTodo = ''
    },
```

this.todosにpushしています。
pushとはリスト形式の変数にレコードを追加する処理です。
this.todosはdataの中に定義されていましたね。ここにレコードを追加しています。
どんなレコードかというと、idが todoStorage.uid++,titleがvalue(入力された値),completedがfalseです。
titleとcompletedはなんとなく分かりますが、todoStorage.uid++とはいったい。。。

#### ・todoStorage
このあたり少しややこしいです。

todoStorageは以下で定義されています。

```javascript:JavaScript
var todoStorage = {
  fetch: function () {
    var todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')
    todos.forEach(function (todo, index) {
      todo.id = index
    })
    todoStorage.uid = todos.length
    return todos
  },
  save: function (todos) {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
  }
}
```

#### ・save

```javascript:JavaScript
  save: function (todos) {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
  }
```
先にsaveから見てみます。
todoStorage.saveが呼び出された際にはlocalStorageにtodosをJSON形式にして格納しています。
localStorageとはクライアントサイドストレージといって、ブラウザ自体にデータを格納する際の格納場所です。[^4]
これによってブラウザをリロードしてもデータを保持しておけます。

#### ・fetch
```javascript:JavaScript
  fetch: function () {
    var todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')
    todos.forEach(function (todo, index) {
      todo.id = index
    })
    todoStorage.uid = todos.length
    return todos
  }
```
次にfetch。
saveで格納しておいたデータを取り出しています。
その後、forEachでtodos内の要素を1つずつ取り出してtodoとしています。
indexは0からの連番が設定されるので、この値をtodo.idに設定していますね。
そしてtodosの長さ、つまりリストの件数をtodoStorage.uidとして保持しています。

これ、何をやっているかというと、初期表示時のデータ設定を行っています。
初期表示時にtodosのデータとしてtodoStorage.fetch()のリターン値を設定しています。
localStorageにデータが格納されていればそれを返却します。
localStorageへのデータ格納はsaveにて行っています。

#### ・話は戻って todoStorage.uid++
寄り道しましたが、つまりaddTodoのtodos.pushでtodoStorage.uid++としていたのは次のリストが何番目かを設定していたのです。
リストに1つTODOが存在している場合、ここで設定されるidは2ですね。

これでaddTodoの動作は一通り理解できたと思います。

#### ・watchでのtodos監視
ですが、TODO追加時に動作するのはaddTodoだけではありません。
監視プロパティwatchでtodosが定義されています。
watch内に定義された変数に変更があった場合、つまり今回はaddTodo内でtodosにpushしたことによって
todosの内容は変更されたので、コールバック処理が実行されます。[^5]
コールバック処理とは以下の部分のことです。

```javascript:JavaScript
  todoStorage.save(todos)
```

これは先ほど出てきましたね。

```javascript:JavaScript
var todoStorage = {
  save: function (todos) {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
  }
}
```
localStorageにtodosをJSON形式にして格納しています。

#### ・TODO追加のまとめ

TODO追加時の処理についてのおさらいです。

![プレゼンテーション1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251494/3beb0b20-548b-6ed1-518f-4bba96a39fe8.jpeg)



# まとめ
初投稿なので至らない部分があるかもしれません。ご指摘、ご指南よろしくお願いいたします。
Vue.jsについても私自身勉強中なので勉強しながら記事を書いています。
初心者向けに分かりやすく詳しく書いたつもりなので、いいねしてくれるとうれしいです。

次回があれば「TODO削除」について見ていこうと思います。

**追記：次回がありました！**
[**【Vue.js初心者】Todoリストはこう作る！～Todo削除～**](https://qiita.com/kya0707/items/93a503612f164ed019df)

# 参考

[^1]: [Vue.js公式ドキュメント_v-on](https://jp.vuejs.org/v2/guide/events.html#%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%AE%E8%B3%BC%E8%AA%AD)

[^2]: [Vue.js公式ドキュメント_v-on省略記法](https://jp.vuejs.org/v2/guide/syntax.html#v-on-%E7%9C%81%E7%95%A5%E8%A8%98%E6%B3%95)

[^3]: [Vue.js公式ドキュメント_v-model](https://jp.vuejs.org/v2/guide/index.html#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E5%85%A5%E5%8A%9B%E3%81%AE%E5%88%B6%E5%BE%A1)

[^4]: [Vue.js公式ドキュメント_クライアントサイドストレージ](https://jp.vuejs.org/v2/cookbook/client-side-storage.html)

[^5]: [Vue.js公式ドキュメント_監視プロパティ](https://jp.vuejs.org/v2/guide/computed.html#%E7%AE%97%E5%87%BA%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3-vs-%E7%9B%A3%E8%A6%96%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3)