vue.js+firebase+vuefireで作るチャット

# 仕様

* vue.js 2.5.13
* firebase 2.3.2
* vuefire 1.4.4
* rails 5.1.4
* ruby 2.3.0p0 (2015-12-25 revision 53290)

でチャットアプリを作る。webでサーバの設定とかを気にせずチャットを作りたいなと思い、firebaseを用いることにした。

# vuefireについて

https://github.com/vuejs/vuefire

vuefireはvue.jsのdataとfirebaseをバインディングしてくれるもの。

# やったこと

## vue.jsの導入

npm、webpackerを用いて導入。packフォルダ内にてjavascriptを記入していく。vue.jsは対象のidのものが先に読み込まれていないと発火しないのでbody閉じタグ前にjavascriptを記載する必要がある。

## firebaseの導入

```
<!--firebaseのライブラリ読み込み-->
<script src="https://cdn.firebase.com/js/client/2.3.2/firebase.js"></script>
```

firebaseのライブラリを読み込み、下記をfirebaseアカウントからコピペしてもってくる


```javascript:index
<script src="https://www.gstatic.com/firebasejs/4.8.1/firebase.js"></script>
<script>
  // Initialize Firebase
  var config = {
    apiKey: "",
    authDomain: "",
    databaseURL: "",
    projectId: "",
    storageBucket: "",
    messagingSenderId: ""
  };
  firebase.initializeApp(config);
</script>
```

これでfirebaseの導入は終わり。簡単。

## vuefireの導入

```html:index.html
<head>
  <!-- Vue -->
  <script src="https://unpkg.com/vue/dist/vue.js"></script>
  <!-- Firebase -->
  <script src="https://gstatic.com/firebasejs/4.0.0/firebase.js"></script>
  <!-- VueFire -->
  <script src="https://unpkg.com/vuefire/dist/vuefire.js"></script>
</head>
```

```javascript:chat.js
var Vue = require('vue')
var firebase = require('firebase')
var VueFire = require('vuefire')

// explicit installation required in module environments
Vue.use(VueFire)
```
下２行がvuefire関連


## コードをつらつらと書く

```html:index.html
<div id="chat">
<ul is="transition-group">
  <li v-for="message in messages" :key="message['.key']">
    {{message.contents}}
  </li>
</ul>

 <form v-on:submit.prevent="addMessage" class="form-inline" >
   <input type="text" id="form_board_id" value="<%= @post.id %>" class="hidden">
   <input type="text" id="form_user_id" value="<%= @current_user.id %>" class="hidden">
   <input type="text" name="" v-model="message.contents" class="col-sm-8 form-control show_form">
   <button type="submit" name="button" class="btn btn-primary col-sm-3">送信</button>
 </form>
</div><!--chat-->
```

```javascript:chat.js
import Vue from 'vue/dist/vue.esm';
import App from '../app.vue'
var VueFire = require("vuefire");
var Firebase = require("firebase");
Vue.use(VueFire)

var form_user_id = document.getElementById("form_user_id").value;
console.log(form_user_id);
var form_board_id = document.getElementById("form_board_id").value;
console.log(form_board_id);
var firetalks = firebase.database().ref('talks')
var chat = new Vue({
  el: "#chat",
  data: {
    message: {
      user_id:form_user_id,
      board_id:form_board_id,
      contents:'',
    }
  },
  firebase: {
      messages: firetalks
  },
  methods: {
    addMessage: function(){
      firetalks.push(this.message)
      this.message.user_id = ''
      this.message.board_id = ''
      this.message.contents = ''
      }
    }
})
```

### 全体的にやっていること

v-modelでユーザーの記入した情報を渡しているが他の情報も一緒に渡したい場合、vue.jsは初期値を無視するのでもともと入れておいてhiddenで隠して送信ができない。しょうがないのでjavascriptのgetElementByIdで送る。submitボタンを押したらmethodsのaddMessageを発火させ、firebaseに送る。そしてそのfirebaseの中身をvue.jsで描写する。

```
      this.message.user_id = ''
      this.message.board_id = ''
      this.message.contents = ''
```

の部分は送った後に空に戻すためのもの。（他の記事を参考にしたんだが最初これなんだ？と思って書いてなかった。。。）

### チャット機能をmethodsで定義

```javascript
  methods: {
    addMessage: function(){
      firetalks.push(this.message)
      this.message.user_id = ''
      this.message.board_id = ''
      this.message.contents = ''
      }
    }
```
messageにvueのインスタンスが入っているのでそれをpushでfirebaseに送っている。pushはfirebaseのメソッド。

### firebaseとのバインディング

```javascript:chat.js
  firebase: {
      messages: firetalks
  },
```
このfirebaseというのはvuefireを導入すると使えるものでmessagesプロパティに右側のref以下のfirebaseのjsonを紐付けられる。このfiretalksにtalk以下を紐付けている。

# つまりどころ

## vue.jsのバージョンがかわりまくっててドキュメント探しが大変だった

vue.jsのドキュメント自体はまあまああるんだけどバージョン変ると全然仕様が違って大変だった。。。バージョンの確認をしよう！

## どうやってフォームに入力していない情報をvue.jsに渡すか

vue.jsは初期値を無視するのでよくrailsでやっていたvieに初期値を入れてhiddenで隠して一緒に送るができなくて大分苦労した。対処は下記の記事に。

https://qiita.com/you88/items/2051d48454038b78792d

## v-forの仕方

```javascript
<ul is="transition-group">
  <li v-for="message in messages" :key="message['.key']">
    {{message.contents}}
  </li>
</ul>
```
messagesがfirebase:で定義したプロパティでこれをmessageというエイリアスで繰り返している。