【Vue.js/firebase】ToDoリストを作る

Vue.jsとfirebaseを使い、ToDoリストを作ってみました。

学習の記録として作成手順を残しておきたいと思います。

##プロジェクトを作成する
プロジェクトを作成したいディレクトリに移動し、下記コマンドを実行する。
ここではvue-todoというプロジェクト名をつけました。

```
¥ vue create vue-todo
```

質問形式で設定を聞かれるので、スペースキーで選択し Enter で進めます。

プロジェクト作成が完了したら、VSccodeでvue-todoフォルダを開きます。
続いて下記コマンドを実行し、firebaseライブラリをインストール、サーバーを起動します。


```
¥ npm add firebase
¥ npm run serve
```

localhost:8080にアクセスすると、Vue.jsのデフォルトの画面が表示されます。



##firebaseでプロジェクトの準備をする

「firebase　コンソール」とブラウザで検索し、firebaseにGoogleアカウントでログインします。

・firebaseのプロジェクトの準備をしていきます。
プロジェクトを追加　→　プロジェクト名を入力　→　Googleアナリティクスを使うか選択（今回は使わないのでチェックを外します）して作成するをクリック


・データベースの準備をしていきます。
Firestore　→　作成する　→　テストモードを選択して次へ　→　ロケーションを選択（今回はasia-east2）　


・ウェブアプリにFirebaseを追加します。
プロジェクトの概要　→　</>ウェブ　→　アプリの登録でアプリ名を指定（今回はvue-todo）→　アプリの登録をクリック

「Firebase SDKの追加」とスクリプトが出てくるので、scriptタグ内の行をコピーしておきます。

コピーした部分を、main.jsファイルの

```
Vue.config.productionTip = false
```
の直後にペーストします。

Vue.config.productionTip = falseの上に、firebaseをインポートします。

```js:main.js

import firebase from 'firebase'
```


##ToDoリストをつくる

まずApp.vueのデフォルト部分を削除します。（templateタグ内、HelloWorldのコンポーネント）

・templateタグ内に、ToDoリストのテンプレートを記述します。

```vue:App.vue

<template>
  <div id="app">
    <h1>TODOリスト</h1>
    <div>
      <input />
      <button>追加</button>
    </div>
    <ul>
      <li>
        <input type="checkbox" />
        タスク名
        <button>×</button>
      </li>
    </ul>
  </div>
</template>
```

・トップページが表示された時、つまりAppコンポーネントが作成されたときにfirestoreの初期設定を行うよう設定します。

```vue:App.vue

<script>
import firebase from 'firebase'
export default {
  name: 'App',
  data() {
    return {
      db: null,
      todosRef: null
        //以下のcreated()でdb,todosRefを記述しているので、初期値を設定しておく。
    }
  },
  created() {
    this.db = firebase.firestore()
        //おまじないのようなものと覚えておく。
    this.todosRef = this.db.collection('todos')
        //今回データベースにtodosというコレクションをつくる。この参照先を指定。
  }
}
</script>
```


・ToDoリストにタスクを追加します。

```vue:App.vue

<h1>TODOリスト</h1>
    <div>
      <input v-model="newTodoName" />
      <button @click="addTodo()">追加</button>
          //追加ボタンを押すとaddTodoメソッドが呼ばれる。
    </div>
```


```Vue:App.vue
<script>
export default {
  name: 'App',
  data() {
    return {
      db: null,
      todosRef: null,
      newTodoName: ''
    }
  },
  created() {
    this.db = firebase.firestore()
    this.todosRef = this.db.collection('todos')
  }
  methods: {
    addTodo(){
      if(this.newTodoName === ''){ return }
          //何も入力されていなければ、このメソッドを抜ける。
          //以下は入力されていた時のみ実行される。
      this.todosRef.add({
          //firestoreにデータを追加する際はadd()を使う
        name: this.newTodoName,
        isComplete: false,
          //タスクが完了しているかどうかのフラグ。初期値は未完了。
      })
    }
  }
}
</script>
```


動作確認をしてみます。
ブラウザからタスクを入力して追加ボタンを押します。
firebaseコンソール のFirestoreをみると、現在のデータベースの中身を確認することができ、入力したタスクが追加されています。


・ToDo一覧を表示します。

v-forでtodoのnameを表示します。
完了した際にチェックを入れるチェックボックスも実装します。

```vue:App.vue
<ul>
   <li v-for="(todo, key) in todos" :key="key">
      <input type="checkbox" v-model="todo.isComplete" @click="updateTodo(todo, key)" />
     　  {{ todo.name }}
      <button>×</button>
   </li>
</ul>
```

```vue:App.vue
<script>
import firebase from 'firebase'
export default {
  name: 'App',
  data() {
    return {
      db: null,
      todosRef: null,
      newTodoName: '',
      todos: {}
          //オブジェクト形式で返ってくるので、空のオブジェクトを定義する。
    }
  },
  created() {
    this.db = firebase.firestore()
    this.todosRef = this.db.collection('todos')
    this.todosRef.onSnapshot(querySnapshot => {
        //querySnapshotが現在の全体のデータ
      const obj = {}
        //空のオブジェクトを作成
      querySnapshot.forEach(doc => {
        obj[doc.id] = doc.data()
          //作成した空のオブジェクトにデータを入れていく
      })
      this.todos = obj
        //todosにobjをあてる
    })
      //onSnapshotは何かしらの変更があると処理を実行するリスナー
      //データが変わった時に行う処理を記述している
  },
  methods: {
    addTodo(){
      if(this.newTodoName === ''){ return }
      this.todosRef.add({
        name: this.newTodoName,
        isComplete: false,
      })
    },
    updateTodo(todo, key){
      todo.isComplete = !todo.isComplete
　　　　　//isCompleteを反転させる
      this.todosRef.doc(key).update(todo)
    }
  }
}
</script>
```


・削除機能をつけます

削除ボタンをクリックすると、removeTodoメソッドを実行するようにします。
引数にはkeyを指定し、そのデータを削除します。

```vue:App.vue
<button @click="removeTodo(key)">×</button>
```

removeTodoメソッドを定義します。

```vue:App.vue
methods: {
    addTodo(){
      if(this.newTodoName === ''){ return }
      this.todosRef.add({
        name: this.newTodoName,
        isComplete: false,
      })
    },
    updateTodo(todo, key){
      todo.isComplete = !todo.isComplete
      this.todosRef.doc(key).update(todo)
    },
    removeTodo(key){
      this.todosRef.doc(key).delete();
    }
  }
```


これで、タスクを作成・完了したらチェックをつける・タスクを削除する機能を実装することができました。


##Firebase Hostingでデプロイする

ここまでで作成したToDoリストのアプリケーションを、Firebase Hostingを使って一般に公開します。

まずはターミナルでプロジェクトのディレクトリに移動し、下記のコマンドでfirebase CLIをインストールします。

```
$ npm install -g firebase-tools
```

firebaseにログインします。

```
$ firebase login
```

下記のコマンド実行後、選択肢を選んで進んでいきます。

```
$ firebase init
```
Yを押してEnter　→　Hostingをスペースキーで選んでEnter　→　Hostingする対象のプロジェクトを選んでEnter　→　public directoryについてはdistと入力してEnter

これでプロジェクトの初期化が完了しました。

続いてVueCLIのプロジェクトのビルドを行ます。


```
$ npm run build
```

実行するとdistというフォルダが作成されます。これがサーバーにアップされるファイルとなります。

firebaseにデプロイします。

```
$ firebase deploy
```

実行すると、Hosting URLが表示されます。